JSON 支持的的数据格式

JSON

前言

目前 JSON 现在已经成为了前后端前后端交换数据的最常用格式,作为一个前端开发,每天都离不开它。 但针对 JSON,我们还有一些不明白或应该避开的坑在里面。

JSON 是什么

MDN 文档中可以查询到:

JSON 是一种语法,用来序列化对象、数组、数值、字符串、布尔值和 null。

JSON 支持的数据类型

通过定义我们可以了解到,JSON 中支持对象,数组,数字,字符串,布尔值,和 null。 这样在说明太宽泛,针对每一种类型,下面说明 JSON 的支持情况也具体怎么样。

一. JSON 支持格式:对象

对象是一个比较宽泛的概念,JSON 支持的对象,只包含一般的键值对,键值对的属性名只能是字符串,需要用双引号包裹。不包含 JavaScript 中的不可遍历属性。对象中的值也只能包含数组、数字、字符串、布尔值、null,以另一个对象,不可进行对象的嵌套引用。例:

{
    "a": {
        "b": "JSON 支持格式"
    }
}

二. JSON 支持格式:数组

数组中的值也只能包含 JSON 支持的值数组、数字、字符串、布尔值、null、对象。不会包含 length 等不可遍历的其他属性。例:

{ "a": [1, 2, "JSON 支持格式"] } // 可以放在对象
[1, 2, "JSON 支持格式"] // 可以单独存在
[1, [2, 3], { "a": 120 }] // 数组中可以包含对象和其他数组

三. JSON 支持格式:数字

只能是10进制的双精度浮点型数字,支持科学计数法,二进制、八进制、十六进制统统不支持。也不支持 BigInt,所以在针对一些数字类型的 ID 要特别注意,要前后端沟通好长度问题或以字符串格式传输,不然可能会损失精度导致问题。例:

{ "a": 120 } // 一般数字

{ "a": 1.2E3 } // 科学计数法

特别注意:JSON 不支持 NaN 和正负 Infinity

四. JSON 支持格式:字符串

例:

{ "a": "" } // 支持空字符串

{ "a": "JSON 支持格式" }

五. JSON 支持格式:布尔值

支持 true 和 false

六. JSON 支持格式:null

null 在 JSON 中是被支持的,注意 JSON 并不支持 JavaScript 中常用的 undefined,用 JSON 序列化 undefined 时,对应的键会被删除。例:

{ "a": null } // 支持 null

{ "a": undefined } // 这是不支持的

// JavaScript 中执行 JSON.stringify({a: undefined})  时得到空对象
{}

JSON 不支持的数据类型(只列举常见部分)

一. 特殊值

不支持 undefined、NaN、-Infinity、Infinity 等

二. 不支持 Symbol、BigInt

Symbol、BigInt 目前也不支持,BigInt 可以尝试转为字符串进行传输。

三. 其他一些非一般键值对对象

  1. Date 日期对象并不能得到 JSON 的支持,但是我们经常把 Date 对象直接放进数据中传输,这是因为在 Date 有一个 toJSON() 方法,会按国际标准进行日期的序列化,生成固定格式的字符串,序列化后的日期字符串便于识别,并便于重新生成 Date 对象。例:

    const dateString = JSON.stringify(new Date())
    console.log(dateString) // "2021-10-29T02:24:40.552Z"
    

    但直接对序列化后的日期字符串进行 JSON.parse(dateString) 操作并不可行。但可以用 new Date(dateString) 生成新的日期对象。

  2. Set 对象并不能直接进行 JSON.stringify() 进行处理,我们需要把它变成一般数组对象后进行序列化处理。

    JSON.stringify(new Set([1, 2, 3])) // 会得到一个序列化后的空对象 "{}"
    
    JSON.stringify(Array.from(new Set([1, 2, 3]))) // "[1,2,3]"
    
  3. Map 也同理,例:

    JSON.stringify(new Map([['a', 12132], ['b', 'daf121']])) // "{}"
    
    JSON.stringify(Object.fromEntries(new Map([['a', 12132], ['b', 'daf121']]))) // `{"a":12132,"b":"daf121"}`
    
  4. 其他 JS 对象也都基本不能直接进行 JSON.序列化的,但针对一个对象,如果我们需要对它进行 JSON 序列化,但我们并不想对他每次都进行特殊处理,有什么办法吗?答案是有的,JSON.stringify() 实际会跑一个对象的 toJSON() 方法,我会给一个对象添加 toJSON() 方法,就可以愉快地进行 JSON.stringify() 序列化了。例:

    Map.prototype.toJSON = function () { return JSON.stringify(Object.fromEntries(this)) } // 给 Map 原型添加 toJSON 方法
    
    JSON.stringify(new Map([['a', 12132], ['b', 'daf121']])) // 这样就可以正常打印出内容了 '{"a":12132,"b":"daf121"}'
    

评论

0/500

全部评论 (2)

  • lithoge (作者) 2021-10-17 09:35:37

    dfkajk

    1
    /