json准确保留string、number、boolean、null四类原始类型;undefined被静默丢弃,date转为字符串后无法还原,bigint抛错,symbol和function被忽略,大整数因浮点精度限制导致数值失真。

JSON 是一种纯数据交换格式,它不携带类型语义,只定义六种原生类型:字符串、数字、布尔值、null、数组、对象。JavaScript 中的原始类型(如 number、string、boolean、null、undefined)和特殊值(如 Date、RegExp、BigInt、Symbol)在 JSON 序列化与反序列化过程中,会因规范限制而发生不同程度的“类型丢失”。
原始类型中哪些会被准确保留?
-
string、number、boolean、null这四类可被 JSON 完整映射,序列化/反序列化后仍保持原始语义:-
"hello"→"hello"(仍是字符串) -
42→42(仍是 number,但注意精度风险) -
true→true -
null→null
-
-
undefined不是 JSON 合法值,会被静默丢弃:JSON.stringify({ a: 1, b: undefined, c: 2 }) // '{"a":1,"c":2}'键
b直接消失,不会出现在结果中。
非原始类型的典型丢失现象
-
Date 对象 → 序列化为 ISO 字符串,反序列化后是普通字符串,不是
Date实例:const d = new Date('2026-06-05'); JSON.stringify(d) // '"2026-06-05T00:00:00.000Z"' JSON.parse('"2026-06-05T00:00:00.000Z"') // 普通字符串,不是 Date -
BigInt → 直接抛错:
Json Schema Toolkit下载使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
JSON.stringify(123n) // TypeError: Do not know how to serialize a BigInt
-
Symbol → 静默忽略(键或值均不出现):
JSON.stringify({ [Symbol('x')]: 'y', z: 1 }) // '{"z":1}' -
Function / undefined / NaN / Infinity:
- 函数:被跳过;
-
undefined:被跳过; -
NaN和Infinity:序列化为null(不是报错,而是规范约定):JSON.stringify({ a: NaN, b: Infinity }) // '{"a":null,"b":null}'
为什么 number 看似保留却常出问题?
JS 的 number 是双精度浮点数,最大安全整数为 Number.MAX_SAFE_INTEGER(9007199254740991)。超出此范围的大整数(如订单 ID、时间戳)在 JSON 中以数字字面量形式传输时,前端解析即失真:
// 后端发:{"id": 1298035313029456899}
// 前端收到:data.id === 1298035313029456900 // 末位已变
这不是“类型丢失”,而是数值精度丢失,根源在于 JS 数字表示能力的硬限制。
如何应对这些丢失?
- 对
Date:手动转为字符串(如.toISOString()),接收方再new Date(str)构造; - 对
BigInt:必须转为字符串再序列化,例如String(123n),接收方用BigInt(str)还原; - 对
undefined/function/Symbol:若需传递,应提前转换为可序列化结构(如null占位、字符串存函数体、显式字段标记); - 对大整数:后端序列化为字符串(如 Jackson 的
@JsonSerialize(using = ToStringSerializer.class)或 Go 的json:",string"标签),前端按需BigInt()或parseInt()处理; - 对自定义类实例:不要依赖
JSON.stringify()深拷贝,改用structuredClone()(现代环境)、类内toJSON()方法,或显式属性复制。
类型丢失不是 bug,而是 JSON 作为通用数据格式的设计取舍——它只负责数据,不负责行为与结构。










