JSON.parse()是唯一标准解析方式,但会因单引号、末尾逗号、undefined/函数、未引号日期字符串而报SyntaxError;JSON.stringify()会静默忽略undefined/function/Symbol、转NaN/Infinity为null、拒绝循环引用,且不处理不可枚举属性或原型链属性。

JSON 不需要“解析”——JSON.parse() 是唯一标准方式,而 JSON.stringify() 也不是万能序列化工具,它只处理可枚举、无循环、无函数、无 undefined 的纯数据。
JSON.parse() 会直接报错的 4 种常见情况
不是所有字符串都能被 JSON.parse() 安全处理。遇到以下内容会抛 SyntaxError:
- 单引号包裹的字符串:
JSON.parse("{'name': 'Alice'}")→ 错误(必须双引号) - 末尾逗号:
JSON.parse('{"id": 1,}') → 报错(JSON 不允许 trailing comma) - undefined 或函数字面量:
JSON.parse('{"cb": undefined}') → 报错(undefined 不是合法 JSON 值) - 日期字符串未加引号:
JSON.parse('{"at": 2023-01-01}') → 实际解析为{"at": 2022}(先算减法),不是你想要的日期
JSON.stringify() 为什么有时“丢数据”
JSON.stringify() 默认跳过某些值,这不是 bug,是规范行为:
-
undefined、function、Symbol类型的键值会被静默忽略 -
NaN和Infinity被转成null - 循环引用直接抛
TypeError: Converting circular structure to JSON - 对象原型链上的属性、不可枚举属性(如
Object.defineProperty(obj, 'x', { value: 1, enumerable: false }))不会被包含
若需保留函数或处理循环引用,必须自己实现 replacer 函数或用第三方库(如 flatted)。
立即学习“Java免费学习笔记(深入)”;
本书是全面讲述PHP与MySQL的经典之作,书中不但全面介绍了两种技术的核心特性,还讲解了如何高效地结合这两种技术构建健壮的数据驱动的应用程序。本书涵盖了两种技术新版本中出现的最新特性,书中大量实际的示例和深入的分析均来自于作者在这方面多年的专业经验,可用于解决开发者在实际中所面临的各种挑战。 本书内容全面深入,适合各层次PHP和MySQL开发人员阅读,既是优秀的学习教程,也可用作参考手册。
安全使用 parse + stringify 的最小防御写法
生产环境别裸调用,至少包一层错误捕获和类型校验:
function safeParse(jsonStr) {
try {
const parsed = JSON.parse(jsonStr);
return parsed && typeof parsed === 'object' ? parsed : null;
} catch (e) {
console.warn('Invalid JSON:', e.message);
return null;
}
}
function safeStringify(obj) {
try {
return JSON.stringify(obj);
} catch (e) {
console.warn('Cannot stringify:', e.message);
return null;
}
}
注意:JSON.stringify() 第二个参数(replacer)可用于过滤字段,第三个参数(space)仅用于格式化输出,不影响语义。
和 localStorage 配合时最容易踩的坑
localStorage.setItem('user', obj) 看似能存对象,其实会自动调用 String(obj) → 得到 "[object Object]"。正确写法必须显式 JSON.stringify:
- 存:
localStorage.setItem('user', JSON.stringify(user)) - 取:
const user = JSON.parse(localStorage.getItem('user') || 'null')(注意空值 fallback) - 如果取出来是
null或undefined,JSON.parse(null)会返回null,但JSON.parse(undefined)会报错 —— 所以务必做空判断
真正麻烦的是嵌套结构里混入 Date、RegExp、Map 等类型:它们经 JSON.stringify() 后信息就丢了,还原时得靠额外约定或自定义序列化逻辑。










