随笔- 27  文章- 0  评论- 143 

本文PDF下载

本文结构

结构图

JSON简介

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它易于编程人员阅读和编写,同时也易于机器解析和生成。它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。

客户端

使用JSON方式创建对象

Object方式

function Person(name, age){

     this.Name = name;

     this.Age = age;

}

 

var p = new Person("Sunny D.D", 25);

alert(p.Name) //输出Sunny D.D

alert(p.Age) //输出25

使用上述代码创建对象,需要先写出对象的类,使用new关键字来创建对象。下面将介绍JSON创建对象的方式,它更像C#中的匿名类。

JSON方式

var json = {"Name":"Sunny D.D", "Age":25};

alert(p.Name) //输出Sunny D.D

alert(p.Age) //输出25

可以看出,上述两种方式创建的对象实际上是一样的,但使用JSON方式创建对象更简便,非常适合创建一个临时的用来存储数据的对象。使用JSON方式创建的对象是不是与c#的匿名对象很相似呢?

为什么说使用JSON方式创建的对象与c#的匿名对象很相似,而不是相同呢?因为在C#中,匿名对象是不能传递的,也就是说不能通过参数的形式传递给另一个方法进行处理。但根据JavaScript语言的特点,对于Object对象没有严格的类型限制,这样就可以进行方便的传递了:

function showName(person){

     alert(person.Name);

}

showName(json) //输出Sunny D.D

获取JSON对象的字符串表示

使用json.js可以方便的将对象转换为JSON的字符串形式。下载地址

json.js文件的最下面,可以看到这样一段代码:

if (!Object.prototype.toJSONString) {

    Object.prototype.toJSONString = function (filter) {

        return JSON.stringify(this, filter);

    };

    Object.prototype.parseJSON = function (filter) {

        return JSON.parse(this, filter);

    };

}

可以看到,它将判断对象类型是否有toJSONString这样一个方法,如果没有,将会为对象加入toJSONString方法与parseJSON这两个方法。

引入了这个js文件后,就可以简单地调用toJSONString方法来获取对象的JSON字符串形式:

var jsonStr = p.toJSONString();

输出jsonStr,可以获得字符串"{"Name":"Sunny D.D","Age":25}"

将字符串转换为JSON对象

在引入了json.js后,可以简单地调用JSON.parse(text),或者text.parseJSON()来将字符串转换为对象,但是需要注意的是,在一个string对象上调用parseJSON()时,会报一个错误“illegal access,这是因为在代码“return JSON.parse(this, filter);”处,this的类型是一个Object,这可能是一个bug,稍加改动即可通过:

if (!Object.prototype.toJSONString) {

    Object.prototype.toJSONString = function (filter) {

        return JSON.stringify(this, filter);

    };

    Object.prototype.parseJSON = function (filter) {

        return JSON.parse(this + "", filter);

    };

}

这样就可以确保传递给JSON.parse方法的第一个参数是string类型的对象。

服务器端

LINQ to JSON

获取LINQ to JSON的开源资源,可以访问http://json.codeplex.com/

如果仅使用,可以下载Newtonsoft.Json.dll

在项目中引用Newtonsoft.Json.dll就可以获得LINQ to JSON的能力了。在下面的示例中,我使用到了Northwind数据库,使用LINQ to SQL方式读取所有产品类别数据,创建一个JObject对象:

using (NorthwindDataContext db = new NorthwindDataContext())

{

        JObject json = new JObject( //创建JSON对象

        db.Categories.Select(

            c =>

            new JProperty( //创建JSON属性

                c.CategoryName, //属性名称(在这里是产品类别名称)

                new JArray( //属性的值(在这里是该类别下的所有产品名称)

                    c.Products.Select(

                        p =>

                        p.ProductName

                    )

                )

            )

        )

    );

    ltrJson.Text = json.ToString();

}

上述代码生成的数据结构如下:

类别名称” : [“产品名称”, “产品名称”, “产品名称”,]

, “类别名称” : [“产品名称”, “产品名称”, “产品名称”,]

,……

在前台页面获取ltrJson.Text,然后调用JSON.parse(ltrJson.Text),就可以获取到生成的对象了。

可以看出,LINQ to JSON提供程序支持我们以习惯的LINQ方式读取、创建对象,简化了开发过程,让我们的注意力可以集中在业务流程上。

下面简单地介绍LINQ to JSON中常用的几个类。

LINQ to JSON

JavaScript

描述

JObject

Object

对象

JProperty

string

属性名

JArray

Array

数组

JValue

string,number,object,array,true,false,null

属性的值

使用LINQ to JSON创建的对象,都可以简单地调用ToString方法来获取JSON字符串。此方法有两个重载形式,第一个是无参形式,可以按照默认格式获取JSON字符串;也可以调用有参格式,使用自定义格式来生成JSON字符串。

将字符串转换为JObject对象

在后台程序中可以通过JObject的静态方法Parse将字符串转换为一个JObject对象:

JObject o = JObject.Parse(json);

转换成功后,就可以利用LINQ to JSON的特性来进行相关操作了。

LINQ to JSON中的查询

要使用LINQ to JSON进行查询,就必须要了解它的数据结构:

clip_image002

可以看出,其所有的类都派生于JToken,也就是说所有的LINQ to JSON对象都可以用JToken来表示,即JObjectJProperty还是JArray都可以利用李氏替换原则而用JToken来表示。认清这一点是非常必要的,因为接下来的示例中将多次用到他们之间的类型转换。

遍历一个JToken中所包含的元素,可以使用JTokenObj. Children方法,例如:

using (ProductDataContext db = new ProductDataContext())

{

    JObject json = new JObject( //创建JSON对象

        db.Categories.Select(

            c =>

            new JProperty( //创建JSON属性

                c.CategoryName, //属性名称(在这里是产品类别名称)

                new JArray( //属性的值(在这里是该类别下的所有产品名称)

                    c.Products.Select(

                        p =>

                        p.ProductName

                    )

                )

            )

        )

    );

 

    foreach (JProperty i in json.Children()) //遍历JSON对象的所有属性

    {

        Console.WriteLine("类别为{0}的产品列表", i.Name); //输出属性的名称

        JArray arr = (JArray)i.Value; //获取属性的值(在这里是该类别下的所有产品名称)

        foreach (JValue j in arr) //遍历产品名称集合

        {

            Console.WriteLine(j.Value); //输出产品名称

        }

        Console.WriteLine("-----------------------------------------------------");

    }

上述示例运行后,将输出所有的产品类别,以及属于对应类别的所有产品信息。

既然讲LINQ to JSON,那么就可以在其所有的对象上使用LINQ to Object(标准查询操作符)的方式进行查询。在下面的示例中,演示了如何使用LINQ to Object(标准查询操作符)的方式对JSON对象进行查询:

using (ProductDataContext db = new ProductDataContext())

{

    JObject json = new JObject( //创建JSON对象

        db.Categories.Select(

            c =>

            new JProperty( //创建JSON属性

                c.CategoryName, //属性名称(在这里是产品类别名称)

                new JArray( //属性的值(在这里是该类别下的所有产品名称)

                    c.Products.Select(

                        p =>

                        p.ProductName

                    )

                )

            )

        )

    );

    var q =

        json.Children<JProperty>() //获取JSON对象的所有属性

        .Where(j => j.Name.StartsWith("C")) //结果只包含属性名称以"C"开头的

        .OrderBy(j => ((JArray)j.Value).Count) //以属性的值中包含的元素个数排序

        .Select(j => j.Name); //查询结果仅包含属性名称

    foreach (string i in q) //遍历并输出属性名称

    {

        Console.WriteLine(i);

    }

}

 

LINQ to JSONXmlDocument之间的转换

使用LINQ to JSON,可以方便地在JSON对象与XmlDocument对象间进行转换。在以下两个示例中,演示了转换过程:

XmlDocument对象转换为JSON字符串

string xml = @"<?xml version=""1.0"" standalone=""no""?>

                <root>

                  <person id=""1"">

                  <name>Alan</name>

                  <url>http://www.google.com</url>

                  </person>

                  <person id=""2"">

                  <name>Louis</name>

                  <url>http://www.yahoo.com</url>

                  </person>

                </root>";

XmlDocument xdoc = new XmlDocument();

xdoc.LoadXml(xml);

string jsonText = JsonConvert.SerializeXmlNode(xdoc);

Console.WriteLine(jsonText);

JSON字符串转换为XmlDocument对象

string json = @"{

              ""?xml"": {

                ""@version"": ""1.0"",

                ""@standalone"": ""no""

              },

              ""root"": {

                ""person"": [

                  {

                    ""@id"": ""1"",

                    ""name"": ""Alan"",

                    ""url"": ""http://www.google.com""

                  },

                  {

                    ""@id"": ""2"",

                    ""name"": ""Louis"",

                    ""url"": ""http://www.yahoo.com""

                  }

                ]

              }

            }";

XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json);

 

LINQ to JSON & LINQ to XML

在本文前面的讨论中,已经包含了JSON字符串、LINQ to JSON对象和XmlDocument之间的转换方法,那么LINQ to JSON LINQ to XML之间也是可以互相操作的。但是其具体操作方法及是否必要将在以后讨论,大家也可以进行试验。

AJAX

使用AJAX获取JSON

在实际应用中,常会使用Ajax从后台程序中获取数据,然后呈现在页面中。在本示例中为了简化操作,创建了一个“一般处理程序”(.ashx文件)作为后台数据的提供程序,然后在页面中使用Ajax访问它获取一个JSON对象,然后访问JSON对象的AllProducts属性:

Command/GetProductsByCategoryIDHandler.ashx文件:

<%@ WebHandler Language="C#" Class="GetProductsByCategoryIDHandler" %>

 

using System;

using System.Web;

using System.Linq;

using Newtonsoft.Json.Linq;

 

public class GetProductsByCategoryIDHandler : IHttpHandler {

   

    public void ProcessRequest (HttpContext context) {

        HttpResponse response = context.Response;

        HttpRequest request = context.Request;

        int categoryID = Int32.Parse(request["categoryID"]); //传递过来的类别ID

        JObject json = null;

        using (NorthwindDataContext db=new NorthwindDataContext())

        {

            string[] productNames =

                db.Categories //访问Northwind数据库的产品类别表

                .Single(c => c.CategoryID == categoryID) //根据ID获取唯一实例

                .Products //获取此类别的所有产品

                .Select(p => p.ProductName) //结果只包含产品名称

                .ToArray(); //转换为数组

            //实例化JObject对象,同时为其加入一个名为AllProducts的属性

            json = new JObject(

                new JProperty("AllProducts", new JArray(productNames))

            );

        }

        response.ContentType = "text/plain";

        response.Write(json.ToString());

    }

 

    public bool IsReusable {

        get {

            return false;

        }

    }

 

}

页面代码:

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title>JsonAjax Demo</title>

    <script type="text/javascript" src="CommonFiles/JavaScript/jQuery/jquery-1.4.js"></script>

    <script type="text/javascript" src="CommonFiles/JavaScript/json.js"></script>

    <script type="text/javascript">

        var commandLocation = "Command/GetProductsByCategoryIDHandler.ashx";

        function getProductsByStandard(categoryID) {

            $.ajax({

                url: commandLocation,

                dataType: "json",

                data: "categoryID=" + categoryID,

                success: function(json) {

                    show.innerHTML = json.AllProducts;

                }

            })

        }

    </script>

</head>

<body>

    <div>

        <span id="show"></span>

    </div>

</body>

</html>

然后,在脚本中调用getProductsByStandard(1),就会在页面中显示类别ID1的所有产品的产品名称了。要显示其他类别的产品,只需要改变getProductsByStandard方法的参数即可。

本文中使用到的资源

Northwind数据库下载

json.js下载

Newtonsoft.Json.dll下载

Json.NET资源浏览

 posted on 2010-03-21 15:56 sunny段段 阅读(3188) 评论(14) 编辑 收藏

#1楼   回复 引用 查看   
 玄魂       | 2010-03-21 16:16
Linq To Json....要应用到什么场景中呢
#2楼   回复 引用 查看   
 Dreampuf       | 2010-03-21 18:55
json中的Date对象如何解析到C#下呢?.
#3楼   回复 引用 查看   
 chenkai       | 2010-03-21 19:22
@玄魂
其实 在使用Linq时 常有从Linq中衍生出来的Linq to XML ,Linq to SQL 等 今天换了一个Linq to Json. 很明显Linq操作只是一种方式 一种操作数据工具 和手段 而无论是xml SQL 针对的是不同的数据格式. 严格的来说Linq to Json使用场景同Linq to XML 和Linq to SQL没有多大差别. 只要符合Linq to  json 中数据对象可序列化成JSon对象 利用Linq 操作即可. 目前Linq to Json 在 ?YUI2.0/3.0使用比较多. 建议参考.

#4楼   回复 引用 查看   
 chenkai       | 2010-03-21 19:26
@Dreampuf
这个 你应该说的Ajax中项服务器端请求Json格式数据中DAta 这个Json没有关系.
关系型数据库中 读取数据后. 并封装成独立的对象. 例如一个User表读取出来封装SystemUser对象 装在泛型list中. 那单独的一个SystemUser对象可以通过一个JSon.net序列化类转化成Json 返回到客户端JS中识别.

#5楼[楼主]   回复 引用 查看   
 sunny段段       | 2010-03-21 19:48
@Dreampuf
var json = {
"Name":"Sunny D.D",
"Age":25,
"Birthday":new Date(1984)
};
调用json.toJSONString()可以得到以下字符串
{"Name":"Sunny D.D","Age":25,"Birthday":"1970-01-01T00:00:01.984Z"}
如何在后台解析就看你的了

#6楼   回复 引用 查看   
 consatan       | 2010-03-21 19:54
将JS中的数据类型转成JSON还是用
jsonstr = JSON.stringify(Object);
这样的方式比较好吧
我之前用JSON来保存动态生成的TABLE中的信息
本来是用json.js的,测试的时候也好好的,结果部署后,既然提示我
Object.toJSONString()
出错,我捣鼓了一上午也想出不哪错了...本来测试的时候明明好好的啊
后来只好换成json2.js,不过json2.js里没有
Object.toJSONString()这方法
好在通过
if (!Object.prototype.toJSONString) {
    Object.prototype.toJSONString = function (filter) {
        return JSON.stringify(this, filter);
    };
    Object.prototype.parseJSON = function (filter) {
        return JSON.parse(this + "", filter);
    };
}

这段代码能使json.js中的toJSONString()方法能在json2.js中使用
所以奉劝大家还是用
jsonstr = JSON.stringify(Object);
这个方法比较好...至少我部署完后没提示错误了...

#7楼   回复 引用 查看   
 consatan       | 2010-03-21 19:58
对了,博主知道json.js和json2.js的主要区别吗?
google了下,至少用关键字"json.js json2.js 区别"
找不出...E文我实在不行(但通过翻译json2.js里的注释,貌似json2.js是json.js的升级版,或者说JSON官方目前推荐的是json2.js)

BTW,突然想到用json.js还有个坏处
我上次有个方法是用Object来实现类似Map的功能的(键值对的存储)
因为json.js在Object中添加了parseJSON和toJSONString方法
结果我还得在上面的方法中额外去处parseJSON和toJSONString这2个key...

#8楼[楼主]   回复 引用 查看   
 sunny段段       | 2010-03-21 20:11
@consatan
json2.js与json.js的区别一会我看看。
至于后面一个问题,代码都是开源的你还怕什么,自己写个JSON.parseJSON跟JSON.toJSONString不得了,对象放在参数里传过去……核心代码人家都帮你写好了

#9楼   回复 引用 查看   
 ryanding       | 2010-03-21 20:24
学习了! 俺懂了LINQ 不但可以 ToSQL、ToEntity、 ToXML、ToExcel 还可以ToJson 真是可以TO 太多东西了,LINQ不是一般的强大...
#10楼[楼主]   回复 引用 查看   
 sunny段段       | 2010-03-21 20:27
@ryanding
LINQ本身是个框架,只要实现了某个提供程序,就可以进行使用了。
没准什么时候来个LINQ to AV呢,大家就高兴了~

#11楼   回复 引用 查看   
 consatan       | 2010-03-21 20:40
@sunny段段
后面一个问题?是在Object里添加toJSONString和parseJSON方法这个问题?
这个可是在引用了json.js后就自动添加的哦,不信你单纯引用json.js文件后,然后
var obj = new Object();
for(var row in obj) {
document.write(row);
}
它会输出一个parseJSON和一个toJSONString的key

BTW,终于想起来我上次用json.js的怪问题了
不管在head里引用json.js还是在body里引用json.js
都提示JSON未定义,行199(或200行取决于是否删除了第一句)
json.js是在json官方网站上下载的(除了删除第一句 alert('IMPORTANT: Remove this line from json.js before deployment.'); 外,没做任何改动)
测试的代码
<html>
  <head>
    <title>JSON Test</title>
  </head>
  <body>
    <script type="text/javascript" src="./json.js"></script>
    <script type="text/javascript">
      var obj = new Object();
      obj['hello'] = "world";
      for(var row in obj) {
        document.write(row+"
");
      }
    </script>
  </body>
</html>


当然...测试的前提是你加载json.js没出现和我一样的错误提示...
当然...你说的,改写json.js当然是可以的...但就目前的话,我觉得与其改写json.js,不如直接用json2.js来得方便...

#12楼[楼主]   回复 引用 查看   
 sunny段段       | 2010-03-21 21:06
@consatan
多谢,看来json2.js是json.js的改进版本

#13楼   回复 引用 查看   
 深山老林       | 2010-03-21 23:45
好勇猛的文章。
#14楼   回复 引用 查看   
 寻得乐中乐       | 2011-12-05 23:58
不错,对于LINQ又多了一份了解, ajax那段深得我心