JSON.stringify() 遇循环引用报 TypeError,undefined/function/Symbol 值被静默丢弃;JSON.parse() 遇非法 JSON 立抛 SyntaxError;需 try...catch 处理;安全序列化需 replacer 或专用库;parse 结果无原型/类型信息,需 reviver 手动还原。

JSON.stringify() 什么时候会失败
它本身几乎不会抛错,但传入循环引用对象时会直接报 TypeError: Converting circular structure to JSON。比如:
const obj = { a: 1 };
obj.self = obj;
JSON.stringify(obj); // 报错还有像 undefined、function、Symbol 这类值在序列化时会被静默丢弃(不是报错),容易导致数据丢失却没提示。
- 对象里有
undefined属性 → 序列化后该属性消失 - 值是
function()→ 对应字段被跳过 - 用了
Symbol('key')作属性名 → 完全不进入输出字符串
JSON.parse() 遇到非法 JSON 怎么办
只要字符串不符合 JSON 语法,就会立刻抛 SyntaxError,比如单引号、末尾逗号、注释、未转义的控制字符。常见错误输入:
JSON.parse("{'name': 'Alice'}"); // 单引号 → 报错
JSON.parse('{"age": 25,}'); // 末尾逗号 → 报错
JSON.parse('{"msg": "hello\nworld"}'); // 换行没转义 → 报错别指望它自动修复或宽容处理。如果来源不可控(如用户粘贴、旧系统输出),必须用 try...catch 包裹:try {
const data = JSON.parse(input);
} catch (e) {
console.error('解析失败:', e.message);
// 处理 fallback 或提示用户
}
如何安全地序列化带函数或循环引用的对象
原生 JSON.stringify() 不支持,得自己干预。常用两个方向:
- 用
replacer参数过滤掉非法值:传入函数,对每个键值对做判断,返回要保留的值,或undefined跳过 - 用
JSON.stringify(obj, customReplacer)+ 手动展开循环引用(例如记录已访问对象,遇到重复就替换成"[Circular]") - 更省事:用现成库如
flatted或cycle,它们提供stringify()和parse()的增强版,能处理循环引用
replacer 不能修复 undefined 作为对象属性值的问题——它只影响值,不恢复被删掉的键。
JSON 和 JavaScript 对象的边界在哪
很多人误以为 JSON.parse() 返回的就是“原始对象”,其实它只保证是普通 Object 或 Array,不保留原型、方法、日期实例、正则等。例如:
JSON.parse('{"time": "2023-01-01T00:00:00Z"}').time instanceof Date; // false
JSON.parse('{"pattern": "/\\d+/"}').pattern instanceof RegExp; // false如果你需要还原特定类型,得在 reviver 函数里手动转换:JSON.parse(jsonStr, (key, value) => {
if (key === 'time' && typeof value === 'string') {
return new Date(value);
}
return value;
});这个细节常被忽略,结果拿到字符串还以为是 Date 对象,调 .toISOString() 就崩了。










