65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Webservice 和 JSON 将数据绑定到表格。

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.44/5 (11投票s)

2007年10月12日

4分钟阅读

viewsIcon

52142

downloadIcon

918

使用 WebServices 创建 JSON 应用程序

引言

JavaScript 对象表示法,简称 JSON,旨在成为 XML 的轻量级替代品,当 XML 对于您要实现的目标来说有点过于沉重时。尽管 JSON 不可扩展,因为它使用了固定的数据类型集,但它可以用来以文本形式表示复杂的对象。JSON 是一个理想的数据交换格式,当使用 AJAX 等技术时,您的服务器端对象可以转换为 JSON,发送到客户端,在客户端脚本中进行评估,然后进行操作以构建动态广告、菜单等。

基本 JSON 结构

JSON 由两种所有程序员都熟悉的结构组成,即

  • 对象 - JSON 类型集合,通过键访问。这可以看作是 IDictionary<string, JsonType>
  • 数组 - JSON 类型集合,通过索引访问。这可以看作是 IList<JsonType>

JSON 还定义了四种原始类型

  • 字符串 - 一组由双引号括起来的 Unicode 字符。支持基本控制字符以及四位数的 Unicode 转义序列。
  • 数字 - 可以是负数、包含小数部分和包含指数的数字。
  • 布尔值 - true 或 false。
  • null - null 值。

我不想用细节来烦扰您,但 JSON 规范的链接可以在“参考”部分找到。

代码

NetServ.Net.Json 命名空间中的所有 JSON 类型都实现了 IJsonType 接口。此接口允许通过其 JsonTypeCode 标识类型,并允许其将内容写入 IJsonWriterIJsonType 接口的实现包括 JsonStringJsonNumberJsonBooleanJsonArrayJsonObjectJsonNull。该接口定义如下:

using System;

namespace NetServ.Net.Json
{
    /// <summary>

    /// Defines a JavaScript Object Notation data type.

    /// </summary>

    public interface IJsonType
    {
        /// <summary>

        /// Writes the contents of the Json type using the specified

        /// <see cref="NetServ.Net.Json.IJsonWriter"/>.

        /// </summary>

        /// <param name="writer">The Json writer.</param>

        void Write(IJsonWriter writer);

        /// <summary>

        /// Gets the <see cref="NetServ.Net.Json.JsonTypeCode"/> of the type.

        /// </summary>

        JsonTypeCode JsonTypeCode {
            get;
        }
    }

    /// <summary>

    /// Defines the different types of Json structures and primitives.

    /// </summary>

    [Serializable()]
    public enum JsonTypeCode
    {
        /// <summary>

        /// A unicode encoded string.

        /// </summary>

        String,
        /// <summary>

        /// A number.

        /// </summary>

        Number,
        /// <summary>

        /// A boolean value represented by literal "true" and "false".

        /// </summary>

        Boolean,
        /// <summary>

        /// A null value.

        /// </summary>

        Null,
        /// <summary>

        /// A structured object containing zero or more name/value pairs, 

        /// delimited by curly brackets.

        /// </summary>

        Object,
        /// <summary>

        /// An unordered collection of values, delimted by square brackets.

        /// </summary>

        Array
    }
}

IJsonWriter 接口定义了一个 JSON 写入器。它定义了将 JSON 类型转换为文本所需的基本方法。该接口的一个实现是 JsonWriter 类,它将 JSON 文本写入底层的 TextWriter

using System;

namespace NetServ.Net.Json
{
    /// <summary>

    /// Defines a JavaScript Object Notation writer.

    /// </summary>

    public interface IJsonWriter
    {
        /// <summary>

        /// Writes the start of an array to the underlying data stream.

        /// </summary>

        void WriteBeginArray();        

        /// <summary>

        /// Writes the end of an array to the underlying data stream.

        /// </summary>

        void WriteEndArray();

        /// <summary>

        /// Writes the start of an object to the underlying data stream.

        /// </summary>

        void WriteBeginObject();        

        /// <summary>

        /// Writes the end of an object to the underlying data stream.

        /// </summary>

        void WriteEndObject();

        /// <summary>

        /// Writes a object property name to the underlying data stream.

        /// </summary>

        /// <param name="value">The property name.</param>

        void WriteName(string value);

        /// <summary>

        /// Writes a raw string value to the underlying data stream.

        /// </summary>

        /// <param name="value">The string to write.</param>

        void WriteValue(string value);        
    }
}

.NET 中的使用示例

以下是一个如何构建 JSON 类型集合并将结果写入控制台的简短示例。请注意,一个更复杂的示例,包括多个嵌套对象和数组,已包含在演示项目下载中。

using System;
using NetServ.Net.Json;

namespace JsonTest
{
    [STAThread()]
    public class Program
    {
        public static void Main(string[] args) {

            JsonObject order = new JsonObject();
            JsonObject addr = new JsonObject();
            JsonArray items = new JsonArray();
            JsonObject item;     

            // Add some items into the array.


            item = new JsonObject();
            item.Add("ID", new JsonString("Chicken & Chips"));
            item.Add("Qty", new JsonNumber(2));
            item.Add("Price", new JsonNumber(1.50D));
            item.Add("Req", new JsonString("Plenty of salad."));
            items.Add(item);

            // The less verbose way.


            item = new JsonObject();
            item.Add("ID", "Pizza");
            item.Add("Qty", 1);
            item.Add("Price", 9.60D);
            item.Add("Size", "16\"");
            item.Add("Req", "");
            items.Add(item);

            // Add the address information.


            addr.Add("Street", "16 Bogus Street");
            addr.Add("City", "Bogustown");
            addr.Add("County", "Boguscounty");
            addr.Add("Postcode", "B0GU5");

            // Add the items and address into the order.


            order.Add("Items", items);
            order.Add("Address", addr);
            order.Add("Name", "Andrew Kernahan");
            order.Add("Tel.", "55378008");
            order.Add("Delivery", true);
            order.Add("Total", 12.60D);

            using(JsonWriter writer = new JsonWriter()) {

                // Get the container to write itself and all it's 

                // contained types to the writer.


                order.Write(writer);

                // Print the result.


                Console.WriteLine(writer.ToString());
            }
        }
    }
}

使用 JsonWriter 将产生最紧凑的输出。另一个 IJsonWriterIndentedJsonWriter,它将产生缩进的输出,如果需要,人类可以轻松阅读。当使用 IndentedJsonWriter 时,上面的示例将产生以下输出。

{
    "Items":
    [
        {
            "ID": "Chicken & Chips",
            "Qty": 2,
            "Price": 1.5,
            "Req": "Plenty of salad."
        },
        {
            "ID": "Pizza",
            "Qty": 1,
            "Price": 9.6,
            "Size": "16\"",
            "Req": ""
        }
    ],
    "Address":
    {
        "Street": "16 Bogus Street",
        "City": "Bogustown",
        "County": "Boguscounty",
        "Postcode": "B0GU5"
    },
    "Name": "Andrew Kernahan",
    "Tel.": "55378008",
    "Delivery": true,
    "Total": 12.6
}

JsonParser 类用于构建从 TextReader 读取的 JSON 类型。下面是一个解析和提取 JSON 类型的简单示例。请注意,更复杂的示例可以在演示项目下载中找到。

using System;
using System.IO;
using NetServ.Net.Json;

namespace JsonTest
{
    public class Program
    {
        [STAThread()]
        public static void Main(string[] args) {

            StringReader rdr = 
          new StringReader("{\"Name\":\"Andy\",\"Age\":23,\"Hungry?\":true}");

            // The parser takes any TextReader derived class as its source.


            JsonParser parser = new JsonParser(rdr, true);

            JsonObject obj = (JsonObject)parser.ParseObject();

            // Get the information from the object.


            JsonString name = (JsonString)obj["Name"];
            JsonNumber age = (JsonNumber)obj["Age"];
            JsonBoolean hungry = (JsonBoolean)obj["Hungry?"];

            // Print out the information.


            Console.WriteLine("Name:\t\t{0}", name.Value);
            Console.WriteLine("Age:\t\t{0}", age.Value.ToString());
            Console.WriteLine("Hungry?:\t{0}", hungry.Value.ToString());        
        }
    }
}

JavaScript 中的使用示例

如果您将 JSON 用作 AJAX 数据交换格式,那么在客户端脚本中使用 JSON 文本会非常简单,如下面的示例所示。

function updateAdvertsCallback(result, context) {

    // result = [

    //  {"AdvertId":"left","InnerHTML":"Some text","ImageSrc":"animage""},

    //  {"AdvertId":"right","InnerHTML":"Some more text",

    //   "ImageSrc":"anotherimage""}

    // ]


    // Use the JavaScript compiler to parse the text and generate

    // the objects.


    var adverts = eval("(" + result + ")");

    // Then access the members as you would normally.


    for(var i = 0; i < adverts.length; ++i) {
        document.getElementById("advertHTML_" + 
              adverts[i].AdvertId).innerHTML = adverts[i].InnerHTML;
        document.getElementById("advertImg_" + 
              adverts[i].AdvertId).src = adverts[i].ImageSrc;
    }
}

您应该意识到,JavaScript 的 eval 函数可以在评估时执行客户端代码,因此仅当您信任 JSON 的来源时才应使用它。另一种方法是使用一个只识别有效 JSON 输入并忽略其他所有内容的解析器。一个好的 JavaScript JSON 解析器可以在这里找到。

关注点

NetServ.Net.Json 命名空间中的大多数 JSON 类型都利用了 C# 的运算符重载的强大功能。这允许您编写非常简洁的代码,精确地表达您想要实现的目标。

// JsonBoolean jb = JsonBoolean.Get(true);

JsonBoolean jb = true;
// JsonNumber jn = new JsonNumber(42);

JsonNumber jn = 42;
// JsonString js = new JsonString("Hello World!");

JsonString js = "Hello World!";

此外,NetServ.Net.Json 库是符合 CLS 标准的,因此可以在任何使用符合 CLS 标准的语言开发的 .NET 项目中使用。

单元测试

下载中包含了该库编译的单元测试。这些测试是与 Marc Clifton 的高级单元测试工具一起编写的。下面可以看到对这 200 个测试的概述。

UnitTest Overview

结论

我承认这篇文章有点轻量级(第一次写,请多包涵!),但希望您能欣赏到 JSON 格式在 XML 对于您的需求来说过于繁重时的有用性。

参考文献

有用链接

  • json.js - JavaScript JSON 解析器。
  • AJAX - CodeProject 关于 AJAX 的文章。
  • AUT - Marc Clifton 的高级单元测试工具。

历史

  • 2007 年 1 月 16 日 - v1.1 首次公开发布。
© . All rights reserved.