JSON资料整理
目录
原始方式
通用方式
内置方式
契约方式
1.什么是JSON
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于JavaScript的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成。
2.JSON语法规则
JSON 语法是 JavaScript 对象表示法语法的子集。
l 数据在名称/值对中
l 数据由逗号分隔
l 花括号保存对象
l 方括号保存数组
JSON 数据的书写格式是:名称/值对。
名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:
"firstName" : "John"
这很容易理解,等价于这条 JavaScript 语句:
firstName = "John"
JSON 值可以是:
l 数字(整数或浮点数)
l 字符串(在双引号中)
l 逻辑值(true 或 false)
l 数组(在方括号中)
l 对象(在花括号中)
l null
JSON在线校验格式化工具:bejson
3.JSON基础结构
JSON建构有两种结构
JSON简单说就是javascript中的对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表示各种复杂的结构。
1、对象:对象在js中表示为“{}”括起来的内容,数据结构为 {key:value,key:value,...}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值,所以很容易理解,取值方法为 对象.key 获取属性值,这个属性值的类型可以是 数字、字符串、数组、对象几种。
2、数组:数组在js中是中括号“[]”括起来的内容,数据结构为 ["java","javascript","vb",...],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是 数字、字符串、数组、对象几种。
经过对象、数组2种结构就可以组合成复杂的数据结构了。
4.JSON基础示例
简单地说,JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在函数之间轻松地传递这个字符串,或者在异步应用程序中将字符串从 Web 客户机传递给服务器端程序。这个字符串看起来有点儿古怪,但是JavaScript很容易解释它,而且 JSON 可以表示比"名称 / 值对"更复杂的结构。例如,可以表示数组和复杂的对象,而不仅仅是键和值的简单列表。
名称 / 值对
按照最简单的形式,可以用下面这样的 JSON 表示"名称 / 值对":
{ "firstName": "Brett" }
这个示例非常基本,而且实际上比等效的纯文本"名称 / 值对"占用更多的空间:
firstName=Brett
但是,当将多个"名称 / 值对"串在一起时,JSON 就会体现出它的价值了。首先,可以创建包含多个"名称 / 值对"的 记录,比如:
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa" }
从语法方面来看,这与"名称 / 值对"相比并没有很大的优势,但是在这种情况下 JSON 更容易使用,而且可读性更好。例如,它明确地表示以上三个值都是同一记录的一部分;花括号使这些值有了某种联系。
表示数组
当需要表示一组值时,JSON 不但能够提高可读性,而且可以减少复杂性。例如,假设您希望表示一个人名列表。在XML中,需要许多开始标记和结束标记;如果使用典型的名称 / 值对(就像在本系列前面文章中看到的那种名称 / 值对),那么必须建立一种专有的数据格式,或者将键名称修改为 person1-firstName这样的形式。
如果使用 JSON,就只需将多个带花括号的记录分组在一起:
| 
1 
2 
3 
4 
5 
6 
7 | {"people":
 [                { "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa"},                { "firstName": "Jason", "lastName":"Hunter", "email": "bbbb"},                { "firstName": "Elliotte", "lastName":"Harold", "email": "cccc"}            ]} | 
这不难理解。在这个示例中,只有一个名为 people的变量,值是包含三个条目的数组,每个条目是一个人的记录,其中包含名、姓和电子邮件地址。上面的示例演示如何用括号将记录组合成一个值。当然,可以使用相同的语法表示多个值(每个值包含多个记录):
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 | { "programmers":
 [{ "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa"},{ "firstName": "Jason", "lastName":"Hunter", "email": "bbbb"},{ "firstName": "Elliotte", "lastName":"Harold", "email": "cccc"}],"authors":
 [{ "firstName": "Isaac", "lastName": "Asimov", "genre": "science
 fiction"},{ "firstName": "Tad", "lastName": "Williams", "genre": "fantasy"},{ "firstName": "Frank", "lastName": "Peretti", "genre": "christian
 fiction"}],"musicians":
 [{ "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar"},{ "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano"}]
 } | 
这里最值得注意的是,能够表示多个值,每个值进而包含多个值。但是还应该注意,在不同的主条目(programmers、authors 和 musicians)之间,记录中实际的名称 / 值对可以不一样。JSON 是完全动态的,允许在 JSON 结构的中间改变表示数据的方式。
在处理 JSON 格式的数据时,没有需要遵守的预定义的约束。所以,在同样的数据结构中,可以改变表示数据的方式,甚至可以以不同方式表示同一事物。
5.JSON和XML比较
可读性
JSON和XML的可读性可谓不相上下,一边是简易的语法,一边是规范的标签形式,很难分出胜负。
可扩展性
XML天生有很好的扩展性,JSON当然也有,没有什么是XML能扩展,而JSON却不能扩展的。不过JSON在Javascript主场作战,可以存储Javascript复合对象,有着xml不可比拟的优势。
编码难度、解码难度(略)
实例比较
XML和JSON都使用结构化方法来标记数据,下面来做一个简单的比较。
用XML表示中国部分省市数据如下:
<?xml version="1.0" encoding="utf-8"?> <country> <name>中国</name> <province> <name>黑龙江</name> <cities> <city>哈尔滨</city> <city>大庆</city> </cities> </province> <province> <name>广东</name> <cities> <city>广州</city> <city>深圳</city> <city>珠海</city> </cities> </province> <province> <name>台湾</name> <cities> <city>台北</city> <city>高雄</city> </cities> </province> <province> <name>新疆</name> <cities> <city>乌鲁木齐</city> </cities> </province> </country>
用JSON表示如下:
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 | {    "name":"中国",    "province":[    {       "name":"黑龙江",        "cities":{            "city":["哈尔滨","大庆"]        }     },     {        "name":"广东",        "cities":{            "city":["广州","深圳","珠海"]        }    },    {        "name":"台湾",        "cities":{            "city":["台北","高雄"]        }    },    {        "name":"新疆",        "cities":{            "city":["乌鲁木齐"]        }    }]} | 
6. .NET操作JSON
JSON文件读入到内存中就是字符串,.NET操作JSON就是生成与解析JSON字符串。操作JSON通常有以下几种方式:
1. 原始方式:自己按照JSON的语法格式,写代码直接操作JSON字符串。如非必要,应该很少人会走这条路,从头再来的。
2. 通用方式:这种方式是使用开源的类库Newtonsoft.Json(下载地址http://json.codeplex.com/)。下载后加入工程就能用。通常可以使用JObject, JsonReader, JsonWriter处理。这种方式最通用,也最灵活,可以随时修改不爽的地方。
(1)使用JsonReader读Json字符串:
| 
1 
2 
3 
4 
5 
6 | stringjsonText
 = @"{""input""
 : ""value"", ""output"" : ""result""}";JsonReader
 reader = newJsonTextReader(newStringReader(jsonText));while(reader.Read()){    Console.WriteLine(reader.TokenType
 + "\t\t"+
 reader.ValueType + "\t\t"+
 reader.Value);} | 
(2)使用JsonWriter写字符串:
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 | StringWriter
 sw = newStringWriter();JsonWriter
 writer = newJsonTextWriter(sw);writer.WriteStartObject();writer.WritePropertyName("input");writer.WriteValue("value");writer.WritePropertyName("output");writer.WriteValue("result");writer.WriteEndObject();writer.Flush();stringjsonText
 = sw.GetStringBuilder().ToString();Console.WriteLine(jsonText); | 
(3)使用JObject读写字符串:
| 
1 
2 | JObject
 jo = JObject.Parse(jsonText);string[]
 values = jo.Properties().Select(item => item.Value.ToString()).ToArray(); | 
(4)使用JsonSerializer读写对象(基于JsonWriter与JsonReader):
| 
1 
2 
3 
4 
5 
6 
7 
8 | Project
 p = newProject()
 { Input = "stone",
 Output = "gold"};JsonSerializer
 serializer = newJsonSerializer();StringWriter
 sw = newStringWriter();serializer.Serialize(newJsonTextWriter(sw),
 p);Console.WriteLine(sw.GetStringBuilder().ToString());StringReader
 sr = newStringReader(@"{""Input"":""stone"",
 ""Output"":""gold""}");Project
 p1 = (Project)serializer.Deserialize(newJsonTextReader(sr), typeof(Project));Console.WriteLine(p1.Input
 + "=>"+
 p1.Output); | 
上面的代码都是基于下面这个Project类定义:
| 
1 
2 
3 
4 
5 | classProject{    publicstringInput
 { get; set;
 }    publicstringOutput
 { get; set;
 }} | 
此外,如果上面的JsonTextReader等类编译不过的话,说明是我们自己修改过的类,换成你们自己的相关类就可以了,不影响使用。
3. 内置方式:使用.NET Framework 3.5/4.0中提供的System.Web.Script.Serialization命名空间下的JavaScriptSerializer类进行对象的序列化与反序列化,很直接。
| 
1 
2 
3 
4 
5 
6 
7 | Project
 p = newProject()
 { Input = "stone",
 Output = "gold"};JavaScriptSerializer
 serializer = newJavaScriptSerializer();varjson
 = serializer.Serialize(p);Console.WriteLine(json);varp1
 = serializer.Deserialize<Project>(json);Console.WriteLine(p1.Input
 + "=>"+
 p1.Output);Console.WriteLine(ReferenceEquals(p,p1)); | 
注意:如果使用的是VS2010,则要求当前的工程的Target Framework要改成.Net Framework 4,不能使用Client Profile。当然这个System.Web.Extensions.dll主要是Web使用的,直接在Console工程中用感觉有点浪费资源。
此外,从最后一句也可以看到,序列化与反序列化是深拷贝的一种典型的实现方式。
更新1:
注意用System.Web.Script.Serialization的时候,序列化没问题,反序列化会将DateTime赋值成了UTC时间。
UTC时间 + 时区差 = 本地时间
6:02 + (+0800) = 14:02(北京时间)

| 
1 
2 
3 
4 
5 
6 
7 | DateTime
 dt = DateTime.Now;JavaScriptSerializer
 serializer = newJavaScriptSerializer();varjson
 = serializer.Serialize(dt);Console.WriteLine(json);vardt1
 = serializer.Deserialize<DateTime>(json);Response.Write(dt1.ToString()+"<br
 />");Response.Write(ReferenceEquals(dt,
 dt1)); | 
关于UTC时间与北京时间的区别请移步:UTC时间与北京时间差多久?
感谢 @ 老牛吃肉 提醒
4. 契约方式:使用System.Runtime.Serialization.dll提供的DataContractJsonSerializer或者 JsonReaderWriterFactory实现。
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 | Project
 p = newProject()
 { Input = "stone",
 Output = "gold"};DataContractJsonSerializer
 serializer = newDataContractJsonSerializer(p.GetType());stringjsonText; using(MemoryStream
 stream = newMemoryStream()){    serializer.WriteObject(stream,
 p);    jsonText
 = Encoding.UTF8.GetString(stream.ToArray());    Console.WriteLine(jsonText);}using(MemoryStream
 ms = newMemoryStream(Encoding.UTF8.GetBytes(jsonText))){    DataContractJsonSerializer
 serializer1 = newDataContractJsonSerializer(typeof(Project));    Project
 p1 = (Project)serializer1.ReadObject(ms);    Console.WriteLine(p1.Input
 + "=>"+
 p1.Output);} | 
这里要注意,这里的Project类和成员要加相关的Attribute:
| 
1 
2 
3 
4 
5 
6 
7 
8 | [DataContract]classProject{    [DataMember]    publicstringInput
 { get; set;
 }    [DataMember]    publicstringOutput
 { get; set;
 }} | 
实用参考:
JSON验证工具:http://jsonlint.com/
JSON简明教程:http://www.w3school.com.cn/json/
Newtonsoft.Json类库下载:http://json.codeplex.com/
通过序列化将.net对象转换为JSON字符串
在web开发过程中,我们经常需要将从数据库中查询到的数据(一般为一个集合,列表或数组等)转换为JSON格式字符串传回客户端,这就需要进行序列化,这里用到的是JsonConvert对象的SerializeObject方法。其语法格式为:JsonConvert.SerializeObject(object),代码中的”object”就是要序列化的.net对象,序列化后返回的是json字符串。
比如,现在我们有一个TStudent的学生表,表中的字段和已有数据如图所示
 

从表中我们可以看到一共有五条数据,现在我们要从数据库中取出这些数据,然后利用JSON.NET的JsonConvert对象序列化它们为json字符串,并显示在页面上。C#代码如下
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 | protectedvoidPage_Load(objectsender,
 EventArgs e)        {            using(L2SDBDataContext
 db = newL2SDBDataContext())            {                List<Student>
 studentList = newList<Student>();                varquery
 = froms indb.TStudents                            selectnew{                                StudentID=s.StudentID,                                Name=s.Name,                                Hometown=s.Hometown,                                Gender=s.Gender,                                Brithday=s.Birthday,                                ClassID=s.ClassID,                                Weight=s.Weight,                                Height=s.Height,                                Desc=s.Desc                            };                foreach(varitem inquery)                {                    Student
 student = newStudent
 { StudentID=item.StudentID,Name=item.Name,Hometown=item.Hometown,Gender=item.Gender,Brithday=item.Brithday,ClassID=item.ClassID,Weight=item.Weight,Height=item.Height,Desc=item.Desc};                    studentList.Add(student);                }                lbMsg.InnerText
 = JsonConvert.SerializeObject(studentList);            }        } | 
输出结果:
 
从图中我们可以看到,数据库中的5条记录全部取出来并转化为json字符串了。
使用LINQ to JSON定制JSON数据
使用JsonConvert对象的SerializeObject只是简单地将一个list或集合转换为json字符串。但是,有的时候我们的前端框架比如ExtJs对服务端返回的数据格式是有一定要求的,比如下面的数据格式,这时就需要用到JSON.NET的LINQ to JSON,LINQ to JSON的作用就是根据需要的格式来定制json数据。
比如经常用在分页的json格式如代码:
| 
1 
2 
3 
4 
5 
6 | {    "total":
 5, //记录总数    "rows":[        //json格式的数据列表    ]} | 
使用LINQ to JSON前,需要引用Newtonsoft.Json的dll和using Newtonsoft.Json.Linq的命名空间。LINQ to JSON主要使用到JObject, JArray, JProperty和JValue这四个对象,JObject用来生成一个JSON对象,简单来说就是生成”{}”,JArray用来生成一个JSON数组,也就是”[]”,JProperty用来生成一个JSON数据,格式为key/value的值,而JValue则直接生成一个JSON值。下面我们就用LINQ to JSON返回上面分页格式的数据。代码如下:
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 | protectedvoidPage_Load(objectsender,
 EventArgs e)        {            using(L2SDBDataContext
 db = newL2SDBDataContext())            {                //从数据库中取出数据并放到列表list中                List<Student>
 studentList = newList<Student>();                varquery
 = froms indb.TStudents                            selectnew                            {                                StudentID
 = s.StudentID,                                Name
 = s.Name,                                Hometown
 = s.Hometown,                                Gender
 = s.Gender,                                Brithday
 = s.Birthday,                                ClassID
 = s.ClassID,                                Weight
 = s.Weight,                                Height
 = s.Height,                                Desc
 = s.Desc                            };                foreach(varitem inquery)                {                    Student
 student = newStudent
 { StudentID = item.StudentID, Name = item.Name, Hometown = item.Hometown, Gender = item.Gender, Brithday = item.Brithday, ClassID = item.ClassID, Weight = item.Weight, Height = item.Height, Desc = item.Desc };                    studentList.Add(student);                }                 //基于创建的list使用LINQ
 to JSON创建期望格式的JSON数据                lbMsg.InnerText
 = newJObject(                        newJProperty("total",studentList.Count),                        newJProperty("rows",                                newJArray(                                        //使用LINQ
 to JSON可直接在select语句中生成JSON数据对象,无须其它转换过程                                        fromp instudentList                                        selectnewJObject(                                                newJProperty("studentID",p.StudentID),                                                newJProperty("name",p.Name),                                                newJProperty("homeTown",p.Hometown)                                            )                                    )                            )                    ).ToString();            }        } | 
输出结果为:
 
处理客户端提交的JSON数据
客户端提交过来的数据一般都是json字符串,有了更好地进行操作(面向对象的方式),所以我们一般都会想办法将json字符串转换为json对象。例如客户端提交了以下数组格式json字符串。
| 
1 
2 
3 
4 
5 | [    {StudentID:"100",Name:"aaa",Hometown:"china"},    {StudentID:"101",Name:"bbb",Hometown:"us"},    {StudentID:"102",Name:"ccc",Hometown:"england"}] | 
在服务端就可以使用JObject或JArray的Parse方法轻松地将json字符串转换为json对象,然后通过对象的方式提取数据。下面是服务端代码。
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 | protectedvoidPage_Load(objectsender,
 EventArgs e)        {            stringinputJsonString
 = @"                [                    {StudentID:'100',Name:'aaa',Hometown:'china'},                    {StudentID:'101',Name:'bbb',Hometown:'us'},                    {StudentID:'102',Name:'ccc',Hometown:'england'}                ]";            JArray
 jsonObj = JArray.Parse(inputJsonString);            stringmessage
 = @"<table
 border='1'>                    <tr><td
 width='80'>StudentID</td><td width='100'>Name</td><td width='100'>Hometown</td></tr>";            stringtpl
 = "<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>";            foreach(JObject
 jObject injsonObj)            {                message
 += String.Format(tpl, jObject["StudentID"],
 jObject["Name"],jObject["Hometown"]);            }            message
 += "</table>";            lbMsg.InnerHtml
 = message;        } | 
输出结果:
 
当然,服务端除了使用LINQ to JSON来转换json字符串外,也可以使用JsonConvert的DeserializeObject方法。如下面代码实现上面同样的功能。
| 
1 
2 
3 
4 
5 | List<Student>
 studentList = JsonConvert.DeserializeObject<List<Student>>(inputJsonString);//注意这里必须为List<Student>类型,因为客户端提交的是一个数组json            foreach(Student
 student instudentList)            {                message
 += String.Format(tpl, student.StudentID, student.Name,student.Hometown);            } | 
总结:
在客户端,读写json对象可以使用”.”操作符或”["key”]”,json字符串转换为json对象使用eval()函数。
在服务端,由.net对象转换json字符串优先使用JsonConvert对象的SerializeObject方法,定制输出json字符串使用LINQ to JSON。由json字符串转换为.net对象优先使用JsonConvert对象的DeserializeObject方法,然后也可以使用LINQ to JSON。
 
                    
                     
                    
                 
                    
                

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号