json序列化bigint报typeerror因类型不支持,需replacer转字符串并标识;循环引用报错因结构限制,可用weakmap跳过或structuredclone解环;二者可合并处理,同时注意undefined、function等静默丢失问题。

JavaScript 中 JSON 序列化遇到大整数(BigInt)或循环引用时,都会直接报错,但原因和解决路径不同:前者是类型不被支持,后者是结构不被允许。安全处理的关键是**提前识别、主动干预**,而不是依赖 JSON.stringify() 默认行为。
处理 BigInt 导致的 TypeError
JSON.stringify(123n) 会抛出 TypeError: Do not know how to serialize a BigInt。原生 JSON 规范不包含 BigInt 类型,必须手动转换。
- 用 replacer 函数统一转为字符串并加标识,例如:
JSON.stringify(obj, (k, v) => typeof v === 'bigint' ? { _type: 'bigint', value: v.toString() } : v) - 反序列化时用 reviver还原:
JSON.parse(str, (k, v) => v?._type === 'bigint' ? BigInt(v.value) : v) - 若只需展示或传输,且后端能约定格式,可直接转字符串:
v.toString(),但需确保接收方明确知道这是大整数
处理循环引用导致的 TypeError
JSON.stringify({ a: {} }); obj.a = obj; 会报 Converting circular structure to JSON。这不是 bug,是 JSON 标准限制——它无法表达引用关系。
- 最轻量方案:用 WeakMap + replacer跳过重复对象
记录已访问引用,再次出现时返回undefined(字段被忽略)或"[Circular]"(保留标记) - 现代环境推荐:structuredClone() 预处理
JSON.stringify(structuredClone(obj))—— 它会自动解环生成新对象,再序列化就安全了(注意:不支持function、undefined、Symbol) - 需要反序列化后还原引用?用 flatted 库
import { stringify, parse } from 'flatted';输出仍是标准 JSON 字符串,但含{"#": 1}这类引用标记,必须用flatted.parse()才能重建循环
兼顾两者:一个通用 replacer 示例
如果对象里既有 BigInt 又可能有循环引用,可以合并处理:
const seen = new WeakMap();
const replacer = (key, value) => {
if (typeof value === 'bigint') return value.toString(); // 转字符串
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) return '[Circular]'; // 循环引用标为字符串
seen.set(value, true);
}
return value;
};
JSON.stringify(obj, replacer, 2);
额外提醒:别忽略其他静默陷阱
除了大整数和循环引用,这些也会让 JSON.stringify() “悄悄丢数据”:
-
undefined和function:整个键值对被跳过 -
Symbol键:对应属性完全消失 -
Date:自动转成 ISO 字符串,但有时你需要毫秒数或自定义格式 -
Map/Set:原生不支持,需先转成数组或普通对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











