JavaScript操作JSON仅用JSON.stringify()和JSON.parse();前者用于序列化纯数据结构(需避函数/Date/undefined/循环引用),后者解析前须确认输入为合法双引号JSON字符串,且推荐用Response.json()替代手动解析。

JavaScript 里操作 JSON 就是用 JSON.stringify() 和 JSON.parse(),没有别的标准 API。别被“教程”俩字带偏——它不复杂,但容易在细节上翻车。
什么时候必须用 JSON.stringify()?
不是所有对象都能直接发给后端或存进 localStorage。只有纯数据结构(比如不含函数、Date、undefined、循环引用)才能安全序列化。
- 发送请求前:把 JS 对象转成字符串传给接口,比如
fetch(url, { method: 'POST', body: JSON.stringify(data) }) - 存本地存储:
localStorage.setItem('user', JSON.stringify(user)),因为localStorage只接受字符串值 - 调试时快速看结构:
console.log(JSON.stringify(obj, null, 2))(加缩进更易读)
注意:JSON.stringify(new Date()) 得到的是 ISO 字符串,不是 Date 对象;JSON.stringify({ x: undefined }) 会直接忽略 x 属性;遇到循环引用直接抛错 TypeError: Converting circular structure to JSON。
为什么 JSON.parse() 常报 SyntaxError?
错误几乎都来自输入不是合法 JSON 字符串。常见原因:
立即学习“Java免费学习笔记(深入)”;
- 后端返回了 HTML(比如 500 错误页)或纯文本,却直接丢给
JSON.parse() - 字符串里用了单引号:
JSON.parse("{'x':1}")→ 报错,JSON 规范只认双引号 - 末尾多了逗号:
JSON.parse('{"x":1,}') → SyntaxError - 包含注释或 JS 特有语法(如
Infinity、NaN),JSON 不支持
稳妥做法是先检查响应类型和状态:if (res.ok && res.headers.get('content-type')?.includes('json')) { data = await res.json(); } —— 直接用 Response.json() 比手动 JSON.parse() 更安全。
JSON.stringify() 的第三个参数怎么用?
第三个参数控制格式化输出,不是可有可无的装饰项,而是解决实际问题的工具:
- 传数字(如
2):表示缩进空格数,适合日志或调试输出 - 传字符串(如
'→ '):用该字符串代替空格缩进,可用于生成带前缀的文档 - 传数组(如
['name', 'id']):白名单过滤字段,只序列化指定 key,比手写map更轻量 - 传函数(replacer):可处理
Date、BigInt等非法类型,例如:JSON.stringify(obj, (k, v) => v instanceof Date ? v.toISOString() : v)
注意:replacer 函数对 undefined 返回值会删掉该属性,返回 null 则保留 null 字面量。
遇到 BigInt 或 Map 怎么办?
JSON.stringify() 原生不支持 BigInt(直接报错)、Map、Set、RegExp 等。不能硬套,得提前转换:
-
BigInt:显式转成字符串或数字(注意精度丢失风险),例如JSON.stringify({ id: 123n }, (k, v) => typeof v === 'bigint' ? v.toString() : v) -
Map:先转为对象或数组,Object.fromEntries(map)或[...map] -
undefined/function:replacer 里统一过滤或替换,否则会被静默丢弃
真正麻烦的从来不是语法,而是你不知道某个字段在某次请求里悄悄变成了 BigInt 或嵌套了 Map —— 这类隐性类型变化,往往要等线上报错才暴露。










