第二十三章:JSON
理解JSON最关键的一点是要把它当成一种数据格式, 而不是编程语言。 JSON不属于JavaScript, 它们只是拥有相同的语法而已。 JSON也不是只能在JavaScript中使用, 它是一种通用数据格式。 很多语言都有解析和序列化JSON的内置能力。
23.1 语法
JSON语法支持表示3种类型的值。
- 简单值: 可以是字符串、 数值、 布尔值和null; 不可以是特殊值undefined。
- 对象: 第一种复杂数据类型, 对象表示有序键/值对。 每个值可以是简单值, 也可以是复杂类型。
- 数组: 第二种复杂数据类型, 数组表示可以通过数值索引访问的值的有序列表。 数组的值可以是任意类型, 包括简单值、 对象, 甚至其他数组。
23.1.1 简单值
-
最简单可以是一个数值:
5
-
还可以是字符串
“Hello World”
JavaScript与JSON的区别就是:只能用双引号!
23.1.2 对象
{
“name”:"zyzc",
"age":21,
"sex":"male",
"school":{
"name":"GPNU"
"location":"guangzhou"
}
}
23.1.3 数组
-
简单的数组
[25,"zyzc","hello world"]
-
复杂的数组
[ { "id":"1", "name":"student1", "age":"21" }, { "id":"2", "name":"student2", "age":"22" }, ]
23.3 解析与序列化
以前,JavaScript使用eval()
函数来充当JSON的解析器;
ES5的时候就新增了JSON全局对象,正式引入了解析JSON的能力;
JSON对象提供了两个方法:
stringify()
:将JavaScript序列化为JSON字符串parse()
:JSON解析为原生JavaScript的值
23.3.1 序列化
使用JSON.stringify()
可以将一个JavaScript对象序列化为JSON字符串;
可以接收三个参数:
- JavaScript对象
- 过滤器
- 缩进字符规格
在序列化JavaScript对象的时候:
- 会省略函数和原型成员;
- 会省略值为
undefined
的属性;
只传入JavaScript对象
let book = {
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas",
"Matt Frisbie"],
edition: 4,
year: 2017
};
let jsonText = JSON.stringify(book);
console.log(jsonText);
/*
{"title":"Professional JavaScript","authors":["Nicholas C. Zakas","Matt Frisbie"],"edition":4,"year":2017}
*/
传入过滤器:可以是数组也可以是函数:
let book = {
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas",
"Matt Frisbie"],
edition: 4,
year: 2017
};
let jsonText = JSON.stringify(book,['title','authors']);
console.log(jsonText);
/*
{"title":"Professional JavaScript","authors":["Nicholas C. Zakas","Matt Frisbie"]}
*/
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 "title":
return value;
case "authors":
return value.join(",");
case "year":
return 2022;
case "edition":
return 4;
default:
return value;
}
});
console.log(jsonText);
/*
{"title":"Professional JavaScript","authors":"Nicholas C. Zakas,Matt Frisbie","edition":4,"year":2022}
*/
传入缩进字符规范
let book = {
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas",
"Matt Frisbie"
],
edition: 4,
year: 2017
};
let jsonText = JSON.stringify(book, null, 4); // 以4个字符的空格为缩进规范
console.log(jsonText);
/*
{
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas",
"Matt Frisbie"
],
"edition": 4,
"year": 2017
}
*/
let book = {
title: "Professional JavaScript",
authors: [
"Nicholas C. Zakas",
"Matt Frisbie"
],
edition: 4,
year: 2017
};
let jsonText = JSON.stringify(book, null, '---'); // 以3个字符的-为缩进规范
console.log(jsonText);
/*
{
---"title": "Professional JavaScript",
---"authors": [
------"Nicholas C. Zakas",
------"Matt Frisbie"
---],
---"edition": 4,
---"year": 2017
}
*/
注意:使用字符串的时候,如果长度超过10个,则会在第10个字符串处截断
23.3.2 自定义JSON序列化
有时候, 对象需要在JSON.stringify()
之上自定义JSON序列化。 此时, 可以在要序列化的对象中添加toJSON()
方法, 序列化时会基于这个方法返回适当的JSON表示。
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);
console.log(jsonText); // "Professional JavaScript"
其执行步骤如下:
- 如果可以获取实际的值, 则调用
toJSON()
方法获取实际的值,否则使用默认的序列化。 - 如果提供了第二个参数, 则应用过滤。 传入过滤函数的值就是第(1)步返回的值。
- 第(2)步返回的每个值都会相应地进行序列化。
- 如果提供了第三个参数, 则相应地进行缩进。
23.3.3 解析
使用JSON.parse()
方法可以将JSON数据解析为JavaScript对象
其接收两个参数:
- JSON数据
- 还原函数
在还原函数中:如果返回了undefined
,表示删除该键
这个函数就是序列化的逆向操作