一.JSON语法可以表示以下三种类型的值。
1.简单值
5 //json表示数值5 "hello world" //json表示字符串
javascript 字符串和 json 字符串的最大区别是,json 字符串必须使用双引号(单引号会导致语法错)。
布尔值和null也是有效的 json 形式,但是在实际应用中,json更多的用来表示更复杂的数据结构。
2.对象
//json表达对象 { "name":"unamattin", "age":"18", "scholl":{ "name":"北京大学", "location":"北京" } }
与 javascript 的对象自变量相比,json 对象有两个地方不一样,首先,没有声明变量(json没有变量的概念);其次,没有末尾分号。
这个例子在顶级对象中嵌入了 school 信息。虽然有两个 "name" 属性,但由于它们分别属于不同的对象,因此完全没有问题。不过,同一个对象中绝不应该出现两个同名属性。
3.数组
//json表达数组 [25,"hi",true] //同时也可以把数组和对象结合起来,构成更复杂的数据集合 [ { "title":"professional Javascript ", "authors":[ "Nicholas C. Zakas" ], edition:3, year:2011 }, { "title":"professional Ajax", "authors":[ "Nicholas C. Zakas", "Jeremy Mcpeak", "Joe Fawcett" ], edition:2, year:2008 }, ]
同样要注意,json 数组也没有变量和分号,这个数组包含一些图书的对象,每个对象都有几个属性,其中一个属性是"authors",这个属性的值又是一个数组,对象和数组通常是 json 数据结构的最外层形式。
二.解析与序列化
json 之所以流行,拥有与 javascript 类似的语法并不是全部原因。更重要的一个原因是,可以把 json 数据结构解析为有用的 javascript 对象。
就以上一节包含一组图书的 json 数据结构为例,在解析 javascript 对象后,只需要下面一行简单的代码就可以取得第一本书的书名:
//这里是假设把解析json数据结构后得到的对象保存到变量books中 books[0].title //再看看下面在DOM结构中查找数据的代码 document.getElementsByTagName("book")[0].getAttribute("title") //不难理解,为什么json能够得到开发人员的热烈欢迎了。
1.JSON对象
JSON对象有两个方法:stringify()和parse()。在最简单的情况下,这两个方法分别用于把 javascript 对象序列化为 json 字符串和把 json 字符串解析为原生 javascript 值。例如:
var book={ title:"Javascript", authors:[ "Nicholas C. Zakas" ], edition:3, year:2011 }; var jsonText=JSON.stringify(book);
这个例子使用 JSON.stringify() 把一个javascript对象序列化为一个 JSON 字符串,然后将它保存进变量 jsonText 中。默认情况下,输出的 JSON 字符串不包含任何空格和缩进,因此 jsonText 中的字符串如下:
{"title":"Javascript","authors":["NicholasC.Zakas"],"edition":3,"year":2011}
在序列化 javascript 对象时,所有函数及原型成员都会被忽略,结果中最终都是值为 json 数据类型的实例属性。
将 json 字符串直接传递给 JSON.parse(jsonText) 就可以得到相应的 javascript 值。如下:
var bookCopy=JSON.parse(jsonText);
注意,虽然 book 和 bookCopy 具有相同的属性,但他们是两个独立没有任何的关系,如果传给 JSON.parse() 不是有效的 json,该方法会报错。
2.序列化选项
实际上,JSON.stringify() 还可以接收两个参数,这两个参数用于指定以不同的方式序列化 javascript 对象。
第一个参数是个过滤器,可以是个数组也可以是个函数;第二个参数是一个选项,表示是否在 json 字符串保留缩进。
var book={ title:"Javascript", authors:[ "Nicholas C. Zakas" ], edition:3, }; var jsonText=JSON.stringify(book,["titlt","edition"]) //jsontext {"title":"Javascript","edition":3}
这里的第二个参数是一个数组,包含两个字符串,"titlt","edition",这两个属性与将要序列化的对象是对应的,因此返回的 jsonText 只包含这两个属性。
var jsonText=JSON.stringify(book,function(){ switch(key){ case "authors": return value.join(",") case "year": return 5000; case "edition": return undefined; default: return value; } }); //jsonText {"title":"Javascript","authors":"Nicholas c. Zakas","year":5000}
这里函数过滤器根据传入的键来决定结果。
如果键为"authors",就将数组连接为一个字符串;
如果键为"year",则将其设置为5000;
如果键为"edition",通过返回 undefined 删除该属性;
最后一定要提供 default 项,返回传入的值,以便其它的值能够正常出现在结果中。
要序列化的对象中每一个对象都要经过过滤器,因此数组中每个带有这些属性的经过过滤器之后,每个对象都包含"title","authors","year"属性。
var jsonText=JSON.stringify(book,null,4) //jsonText { title:"Javascript", authors:[ "Nicholas C. Zakas" ], edition:3, } var jsonText=JSON.stringify(book,null,"--") //jsonText { --title:"Javascript", --authors:[ ----"Nicholas C. Zakas" --], edition:3, }
这里添加了第三个参数,控制结果的缩进符和空白符,输出的结果会自动插入了换行符提高可读性。
如果是数值,就代表多少个空格,如果是字符串,这个字符串就会被当做缩进符来使用,缩进字符最多十个。