一、语法

  • JSON语法支持表示3种类型的值:
    • 简单值:字符串、数值、布尔值和null可以在JSON中出现,就像在JavaScript中一样。特殊值undefined不可以。
    • 对象:第一种复杂数据类型,对象表示有序键/值对。每个值可以是简单值,也可以是复杂类型。
    • 数组:第二种复杂数据类型,数组表示可以通过数值索引访问的值的有序列表。数组的值可以是任意类型,包括简单值、对象,甚至其他数组。
  • JSON没有变量声明
  • JSON没有变量、函数或对象实例的概念。JSON的所有记号都只为表示结构化数据
  • 布尔值和null本身也是有效的JSON值。
  • JavaScript字符串与JSON字符串的主要区别是:JSON字符串必须使用双引号
  • 数组在 JSON 中使用 JavaScript 的数组字面量形式表示

二、解析与序列化

1、JSON对象

  • stringify()和parse()方法可用于将JavaScript序列化为JSON字符串,以及将JSON解析为原生JavaScript值。
    • 如果给JSON.parse()传入的JSON字符串无效,则会导致抛出错误。
1
2
3
4
5
6
7
8
9
10
11
12
13
let book = { 
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas",
"Matt Frisbie"
],
edition: 4,
year: 2017
};
let jsonText = JSON.stringify(book);
/*
{"title":"Professional JavaScript","authors":["Nicholas C. Zakas","Matt Frisbie"], "edition":4,"year":2017}
*/

2、序列化选项

  • JSON.stringify()方法除了要序列化的对象,还可以接收两个参数。这两个参数可以用于指定其他序列化JavaScript对象的方式。
    • 第一个参数是过滤器,可以是数组或函数
    • 第二个参数是用于缩进结果JSON字符串的选项
    • 单独或组合使用这些参数可以更好地控制JSON序列化。

1)过滤结果

  • 如果第二个参数是一个数组,那么JSON.stringify()返回的结果只会包含该数组中列出的对象属性
1
2
3
4
5
6
7
8
9
10
11
12
13
let book = { 
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas",
"Matt Frisbie"
],
edition: 4,
year: 2017
};
let jsonText = JSON.stringify(book, ["title", "edition"]);
/*
{"title":"Professional JavaScript","edition":4}
*/
  • 如果第二个参数是一个函数,提供的函数接收两个参数:属性名(key)和属性值(value)。可以根据这个key决定要对相应属性执行什么操作。
  • 函数过滤器会应用到要序列化的对象所包含的所有对象,因此如果数组中包含多个具有这些属性的对象,则序列化之后每个对象都只会剩下上面这些属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let book = { 
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas",
"Matt Frisbie"
],
edition: 4,
year: 2017
};
let jsonText = JSON.stringify(book, (key, value) => {
switch(key) {
case "authors":
return value.join(",")
case "year":
return 5000;
case "edition":
return undefined;
default:
return value;
}
});
/*
{"title":"Professional JavaScript","authors":"Nicholas C. Zakas,Matt Frisbie","year":5000}
*/

2)字符串缩进

  • JSON.stringify()方法的第三个参数控制缩进和空格。
    • 在这个参数是数值时,表示每一级缩进的空格数。
  • JSON.stringify()方法还为方便阅读插入了换行符。
  • 最大缩进值为10,大于10的值会自动设置为10。
  • 如果缩进参数是一个字符串而非数值,那么JSON字符串中就会使用这个字符串而不是空格来缩进。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let book = { 
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas",
"Matt Frisbie"
],
edition: 4,
year: 2017
};
let jsonText = JSON.stringify(book, null, 4);
/*
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas",
"Matt Frisbie"
],
"edition": 4,
"year": 2017
}
*/

3)toJSON()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
let book = { 
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas",
"Matt Frisbie"
],
edition: 4,
year: 2017,
toJSON: function() {
return this.title;
}
};
let jsonText = JSON.stringify(book);

这里book对象中定义的toJSON()方法简单地返回了图书的书名(this.title)。

  • 箭头函数不能用来定义toJSON()方法
    • 主要原因是箭头函数的词法作用域是全局作用域,在这种情况下不合适。
  • toJSON()方法可以与过滤函数一起使用,在把对象传给JSON.stringify()时会执行如下步骤。
    (1)如果可以获取实际的值,则调用toJSON()方法获取实际的值,否则使用默认的序列化。
    (2)如果提供了第二个参数,则应用过滤。传人过滤函数的值就是第(1)步返回的值。
    (3)第(2)步返回的每个值都会相应地进行序列化。
    (4) 如果提供了第三个参数,则相应地进行缩进。

3、解析选项

  • JSON.parse()方法也可以接收一个额外的参数,这个函数会针对每个键/值对都调用一次。
  • 为区别于传给JSON.stringify()的起过滤作用的替代函数(replacer),这个函数被称为还原函数(reviver)。实际上它们的格式完全一样。