JSON

JSON 有什么用

JSON 是一种用户数据交换的文本格式,通常用于在网站上表示和传输数据,比如服务器向客户端发送一些数据,渲染在网页上。

在历史上,XML 曾一度成为互联网存储和传输结构化数据的标准,但是其语法冗余和啰嗦,所以 JSON 出来后迅速取代 XML,目前已经成为交换数据的标准格式。

JSON 是什么

JSON 是 Javascript 的子集,是一种数据格式,利用 JavaScript 的几种模式来表示结构化的数据。

JSON 并不属于 JavaScript,只是它们拥有相同的语法,很多语言都有解析和序列化 JSON 的能力,所以 JSON 是一种通用的数据格式。

JSON 支持 3 种类型的值:简单值、对象、数组。

  1. 简单值包括字符串、数字、布尔、null,但是不包含 undefined。
  2. 对象和数组都是复杂数据类型,对象和数组内的值可以组合任意类型,包括简单值、数组、对象等。

简单值

最简单的 JSON 可以是一个数值或者一个字符串,5 或者‘‘5’’都可以是 JSON,null 和布尔值也可以是 JSON。

需要额外注意

  • 字符串必须由双引号包起来。

  • undefined 会被 JSON 忽略,所以它不是 JSON 里的简单值。

对象

在 JavaScript 中,对象字面量是这样的

javascript
1const person = {
2  name: 'qiuyanxi',
3  age: 29,
4}

如果用 JSON 表示则应该是这样的

json
1{
2  "name": "qiuyanxi",
3  "age": 29
4}

首先 JSON 没有变量声明,其次没有分号,此外所有属性名都必须用双引号包起来。

数组

数组的规则跟对象是一样的,没有变量,没有分号,都需要双引号包起来。以下就是一个 JSON 对象

json
1["1", { "name": "qiuyanxi" }, ["2"]]

数组和对象可以自由组合,以表示更加复杂的数据结构。

JSON 怎么用

普通使用

ES5 增加了 JSON 全局对象,用来引入解析 JSON 的能力。

JSON 对象有两个方法:stringify和 parse

stringify可以把 JavaScript 序列化为 JSON 字符串,parse可以将 JSON 字符串解析为原生 JavaScript 值。

举个例子

javascript
1let book={
2  title:"Profession JavaScript",
3  edition:4,
4  year:2017
5}
6let jsonText=JSON.stringify(book)
7'{"title":"Profession JavaScript","edition":4,"year":2017}' //JSON字符串
8
9JSON.parse(jsonText)
10{title: 'Profession JavaScript', edition: 4, year: 2017}

在序列化 JavaScript 对象时,所有函数和 undefined 都会被忽略

js
1let book = { title: undefined, fn: function () {} }
2JSON.stringify(book)
3;('{}')

将 JSON 字符串解析为 JavaScript 对象时,会创建一个新的对象,能够实现深拷贝。

js
1let book={
2  title:"Profession JavaScript",
3  edition:4,
4  year:2017
5}
6let jsonText=JSON.stringify(book)
7let newObj=JSON.parse(jsonText)
8
9newObj.edition=5
10newObj
11{title: 'Profession JavaScript', edition: 5, year: 2017}
12book
13{title: 'Profession JavaScript', edition: 4, year: 2017}

上面的结果就是深拷贝了一个对象,两者的属性不相交。

序列化选项

JSON.stringify除了可以接收需要序列化的对象,还可以接收两个参数,这两个参数可以指定序列化对象的方式

JSON.stringify 的第二个参数

第二个参数是过滤器,可以是数组或者函数

  • 如果是数组,可以指定需要序列化的属性

    下面例子中,只序列化出

    js
    1let book = {
    2  title: 'Profession JavaScript',
    3  edition: 4,
    4  year: 2017,
    5}
    6JSON.stringify(book, ['edition'])
    7;('{"edition":4}')
  • 如果是函数,这个函数称之为还原函数(replacer),它会接收到两个参数,分别是属性名和属性值,可以根据属性名和属性值来决定序列化做的操作。

javascript
1let book = {
2  title: "Profession JavaScript",
3  edition: 4,
4  year: 2017
5};
6const jsonText = JSON.stringify(book, (key, value) => {
7  switch (key) {
8    case "title":
9      return "title is modified";
10    case "edition":
11      return 5000;
12    case "year":
13      return undefined;
14    default:
15      return value; //一定要return value
16  }
17});
18jsonText {"title":"title is modified","edition":5000}

第一次调用这个函数实际上会传入空字符串 key,值是 book 对象

javascript
1const jsonText = JSON.stringify(book, (key, value) => {
2  console.log('key', key)
3  console.log('value', value)
4})
5// key ""
6// value {title: "Profession JavaScript", edition: 4, year: 2017}

JSON.stringify 的第三个参数

第三个参数可以控制缩进和空格。最大缩进值为 10,大于 10 则自动设置为 10

js
1const jsonText = JSON.stringify(book, null, 5);
2{
3     "title": "Profession JavaScript",
4     "edition": 4,
5     "year": 2017
6}
js
1const jsonText = JSON.stringify(book, null, 10);
2{
3          "title": "Profession JavaScript",
4          "edition": 4,
5          "year": 2017
6}

如果设置为字符串,那么就会自动将空格转为这个字符串,字符串的最大长度限制为 10

js
1const jsonText = JSON.stringify(book, null, "-");
2{
3-"title": "Profession JavaScript",
4-"edition": 4,
5-"year": 2017
6}

toJSON 方法

原生的 Date 对象默认带有 toJSON 方法,可以将 Date 对象转化为 ISO8601 日期字符串,本质上跟 toISOString()方法是一致的。

js
1console.log(new Date().toJSON() === new Date().toISOString()) //true

我们也可以在对象中为自定义序列化添加一个 toJSON 方法,然后用 stringify 去序列化这个对象

js
1let book = {
2  title: 'Profession JavaScript',
3  edition: 4,
4  year: 2017,
5  toJSON: function () {
6    return this.edition
7  },
8}
9console.log(JSON.stringify(book))
10// 4

在JSON.stringify 调用时,会执行以下操作:

  1. 如果可以获取到实际的值,则调用 toJSON 方法获取实际的值,否则使用默认的序列化
  2. 如果提供第二个参数,则应用过滤。传入过滤函数的值就是第 1 步返回的值
  3. 第 2 步返回的值会被序列化
  4. 如果提供了第三个参数,则相应对结果进行缩进

解析选项

JSON.parse接收第二个参数,这个参数是一个函数,称为还原函数(reviver),这个函数的参数跟 JSON.stringify一样,第一个参数为 key,第二个参数为 value。

如果这个还原函数返回 undefined,那么结果会删除相应的键。如果返回其他任何值,则会称为相应键的值插入到结果中。

js
1const jsonText = JSON.stringify(book)
2
3JSON.parse(jsonText, (key, value) => {
4  switch (key) {
5    case 'edition':
6      return 5000
7    case 'title':
8      return undefined
9    case 'year':
10      return null
11    default:
12      return value
13  }
14})
15// {edition: 5000, year: null}

总结

  • JSON 是一种轻量的数据交换格式,可以很方便地表示复杂的数据结构
  • JSON 格式可以表示 JavaScript 中的数字、布尔、字符串、null、数组和对象,但会忽略 undefined 和函数
  • JSON 有两种方法,将 JavaScript 对象转化为 JSON 串的 JSON.stringify()方法和将 JSON 串转化为 JavaScript 值的 JSON.parse()方法
  • 两种方法都有额外的选项参数可以修改默认的行为,实现属性的过滤和修改。