目录

🈁 JavaScript 与 JSON

JavaScript 提供了如下方法:

  • JSON.stringify 将对象转换为 JSON。
  • JSON.parse 将 JSON 转换回对象。

# JSON.stringfy

🌰 例子 / 将对象转换为 JSON 字符串:

let student = {
  name: 'John',
  age: 30,
  isAdmin: false,
  courses: ['html', 'css', 'js'],
  wife: null
};

let json = JSON.stringify(student);
console.log(typeof json) // string
1
2
3
4
5
6
7
8
9
10

注意

注意:JSON 编码的对象与对象字面量有几个重要的区别:

  • 字符串使用双引号。JSON 中没有单引号或反引号。
  • 对象属性名称也是双引号的。这是强制性的。

JSON.stringify 也可以应用于原数据类型。JSON 支持以下数据类型:

  • Objects { ... }
  • Arrays [ ... ]
  • 原始数据类型:
    • 字符串
    • 数值
    • 布尔
    • null

🌰 例子 / JSON.stringify 转换原始数据类型:

alert( JSON.stringify(1) ) // 1
alert( JSON.stringify('test') ) // "test"
alert( JSON.stringify(true) ); // true
alert( JSON.stringify([1, 2, 3]) ); // [1,2,3]
1
2
3
4

JSON 是语言无关的纯数据规范,因此一些特定于 JavaScript 的对象属性会被 JSON.stringify 跳过。

  • 函数属性 (方法)。
  • Symbol 类型的键和值。
  • 存储 undefined 的属性。

🌰 例子:

let user = {
  sayHi() { // 被忽略
    alert("Hello");
  },
  [Symbol("id")]: 123, // 被忽略
  something: undefined // 被忽略
};

console.log(JSON.stringfy(user)) // {}
1
2
3
4
5
6
7
8
9

JSON.stringify 支持嵌套对象转换,并且可以自动对其进行转换。

🌰 例子:

let meetup = {
  title: "Conference",
  room: {
    number: 23,
    participants: ["john", "ann"]
  }
};

console.log(JSON.stringify(meetup))
1
2
3
4
5
6
7
8
9

注意

不允许 循环引用的对象

let room = {
  number: 23
};

let meetup = {
  title: "Conference",
  participants: ["john", "ann"]
};

meetup.place = room;       // meetup 引用了 room
room.occupiedBy = meetup; // room 引用了 meetup

JSON.stringify(meetup);  //  Error: Converting circular structure to JSON
1
2
3
4
5
6
7
8
9
10
11
12
13

# replacer

JSON.stringify 的完整语法是:

JSON.stringify(value[, replacer, space])
1
  • value :要编码的值。
  • replacer :要编码的属性数组或映射函数 function(key, value)
  • space :用于格式化的空格数量。

大部分情况, JSON.stringifyvalue 参数使用。但是,如果需要微调替换过程,比如 过滤掉循环引用,可以使用 JSON.stringifyreplacer ,如果传递一个属性数组给它,那么只有这些属性会被编码。

🌰 例子 :

let room = {
  number: 23
};

let meetup = {
  title: "Conference",
  participants: [{name: "John"}, {name: "Alice"}],
  place: room // meetup 引用了 room
};

room.occupiedBy = meetup; 
console.log(JSON.stringify(meetup, ['title', 'participants'])) // {"title":"Conference","participants":[{},{}]}
1
2
3
4
5
6
7
8
9
10
11
12

属性列表应用于整个对象解构。 name 不在列表中,所以 participants 为空。即便这里存在循环引用,也不会报错。

🌰 例子 / 排除掉循环引用的属性:

可以使用一个函数代替数组作为 replacer ,该函数会为每个 (key,value) 对调用并返回「已替换」的值,该值将替换原有的值。如果值被跳过了,则为 undefined

console.log(SON.stringify(meetup, function replacer(key, value) {
  alert(`${key}: ${value}`);
  return (key == 'occupiedBy') ? undefined : value;
})))

/* key:value pairs that come to replacer:
:             [object Object]
title:        Conference
participants: [object Object],[object Object]
0:            [object Object]
name:         John
1:            [object Object]
name:         Alice
place:        [object Object]
number:       23
occupiedBy: [object Object]
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

注意 replacer 函数会获取每个键 / 值对,包括嵌套对象和数组项。它被递归地应用。 replacer 中的 this 的值是包含当前属性的对象。

第一个调用很特别。它是使用特殊的「包装对象」制作的: {"": meetup} 。即第一个 (key, value) 对的键是空的,并且该值是整个目标对象。这就是上面的示例中第一行是 ":[object Object]" 的原因。

函数是为了给 replacer 提供尽可能多的功能:如果有必要,它有机会分析并替换 / 跳过整个对象。

# space 格式化

JSON.stringify(value, replacer, spaces) 的第三个参数是用于优化格式的空格数量(缩进)。

# toJSON

toString 进行字符串转换,对象也可以提供 toJSON 方法来进行 JSON 转换。如果可用, JSON.stringify 会自动调用它。

🌰 例子:

let room = {
  number: 23,
  toJSON() {
    return this.number;
  }
};

let meetup = {
  title: "Conference",
  room
};

alert( JSON.stringify(room) ); // 23

alert( JSON.stringify(meetup) );
/*
  {
    "title":"Conference",
    "room": 23
  }
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

toJSON 既可以用于直接调用 JSON.stringify(room) 也可以用于当 room 嵌套在另一个编码对象中时。

# JSON.parse

语法: JSON.parse(str, [reviver])

  • str :要解析的字符串。
  • reviver :可选参数,该函数将为每个 (key, value) 对调用,并可以对值进行转换。

🌰 例子 / 字符串化数组:

let numbers = "[0, 1, 2, 3]";
numbers = JSON.parse(numbers);
1
2

🌰 例子 / 嵌套对象的字符串:

let userData = '{ "name": "John", "age": 35, "isAdmin": false, "friends": [0,1,2,3] }';
let user = JSON.parse(userData);
1
2

JSON 可能会非常复杂,对象和数组可以包含其他对象和数组。但是它们必须遵循相同的 JSON 格式。

⚠️ JSON 不支持注释。向 JSON 添加注释无效。

# receiver

🌰 例子 / 处理 JSON 字符串中的特定属性类型 Date

let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';

let meetup = JSON.parse(str, function(key, value) {
  if (key == 'date') return new Date(value);
  return value;
});
console.log(meetup.date.getDate())
1
2
3
4
5
6
7

🌰 例子 / 同样适用于嵌套的对象:

let schedule = `{
  "meetups": [
    {"title":"Conference","date":"2017-11-30T12:00:00.000Z"},
    {"title":"Birthday","date":"2017-04-18T12:00:00.000Z"}
  ]
}`;

schedule = JSON.parse(schedule, function(key, value) {
  if (key == 'date') return new Date(value);
  return value;
});

console.log( schedule.meetups[1].date.getDate() );
1
2
3
4
5
6
7
8
9
10
11
12
13

# JSON 总结

  • JSON 是一种数据格式,具有自己的独立标准和大多数编程语言的库。
  • JSON 支持对象、数组和原始数据类型。
  • JavaScript 提供序列化成 JSON 的方法 JSON.stringify (opens new window) 和解析 JSON 的方法 JSON.parse (opens new window)
    • 支持 replacer / receiver 调用智能 读 / 写 转换函数
📢 上次更新: 2022/09/02, 10:18:16