JSON 是 JavaScript 的一个严格的子集,利用了 JavaScript中的一些模式来表示结构化数据。JSON,最重要的是要理解它是一种数据格式,不是一种编程语言。JSON 并不从属于 JavaScript,很多编程语言都有针对 JSON 的解析器和序列化器。
20.1 语法
JSON 的语法可以表示以下三种类型的值。
- 简单值:使用与 JavaScript 相同的语法,可以在 JSON 中表示字符串、数值、布尔值和 null。
但 JSON
不支持JavaScript 中的特殊值undefined。 - 对象:对象作为一种复杂数据类型,表示的是一组无序的键值对儿。而每个键值对儿中的值可 以是简单值,也可以是复杂数据类型的值。
- 数组:数组也是一种复杂数据类型,表示一组有序的值的列表,可以通过数值索引来访问其中 的值。数组的值也可以是任意类型——简单值、对象或数组。
JSON 不支持变量、函数或对象实例
JavaScript 字符串与 JSON 字符串的最大区别在于,JSON 字符串必须使用双引号
20.2 解析与序列化
JSON 之所以流行,可以把JSON 数据结构解析为有用的 JavaScript 对象。
20.2.1 JSON对象
早期的 JSON 解析器基本上就是使用 JavaScript 的 eval()函数。eval()函数可以解析、解释并返回 JavaScript 对象和数组。
ECMAScript 5 对解析 JSON 的行为进行规范,定义了全局对象 JSON。JSON 对象有两个方法:stringify()和 parse()。
20.2.2 序列化选项
JSON.stringify()除了要序列化的 JavaScript 对象外,还可以接收另外两个参数。
JSON.stringify(value[, replacer [, space]])
- replacer,表示过滤器。可以是数组,也可以是个函数。
- space,表示是否在 JSON 字符串中保留缩进
使用数组过滤结果
var book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011
};
var jsonText = JSON.stringify(book, ["title", "edition"]);
以上例子中第二个参数是个数组,包含两个字符串:"title"和"edition"。这两个属性与将要序列化的对象中的属性是对应的,因此在返回的结果中,就只会包含这两个属性。
{"title":"Professional JavaScript","edition":3}
使用函数过滤结果
var book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
yer: 2011
};
var jsonText = JSON.stringify(book, function(key, value){
switch(key){
case "authors":
return value.join(",")
case "year":
return 5000;
case "edition":
return undefined;
default:
return value;
}
});
序列化后的 JSON 字符串如下所示:
{"title":"Professional JavaScript","authors":"Nicholas C. Zakas","year":5000}
字符串缩进
var book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011
};
var jsonText = JSON.stringify(book, null, 4);
最终保存在 jsonText 中的字符串如下所示:
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
"edition": 3,
"year": 2011
}
toJSON()方法
有时候,JSON.stringify()还是不能满足对某些对象进行自定义序列化的需求。在这些情况下, 可以给对象定义 toJSON()方法,返回其自身的 JSON 数据格式。
toJSON()可以作为函数过滤器的补充,因此理解序列化的内部顺序十分重要。假设把一个对象传 入 JSON.stringify(),序列化该对象的顺序如下。
- 如果存在 toJSON()方法而且能通过它取得有效的值,则调用该方法。否则,返回对象本身。
- 如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值。
- 对第(2)步返回的每个值进行相应的序列化。
- 如果提供了第三个参数,执行相应的格式化。
20.2.3 解析选项
JSON.parse()方法也可以接收另一个参数,该参数是一个函数,这个函数被称为还原函数(reviver)。
var book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011,
releaseDate: new Date(2011, 11, 1)
};
var jsonText = JSON.stringify(book);
var bookCopy = JSON.parse(jsonText, function(key, value){
if (key == "releaseDate"){
return new Date(value);
} else {
return value;
}
});
alert(bookCopy.releaseDate.getFullYear());
还原函数在遇到"releaseDate"键时,会基于相应的值创建一个新的 Date 对象。结果就是 bookCopy.releaseDate 属性中会保存一个 Date 对象。