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免费学习笔记(深入)”;
安全使用 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() 后信息就丢了,还原时得靠额外约定或自定义序列化逻辑。