你跑了代码、看了 Network 面板,然后看到这个:"[object Object]" is not valid JSON。又或者你的 JSON 校验器告诉你 Expected a JSON object, array or literal,或者解析器卡在最后一项后面的那个逗号上。这些错误是开发者最常遇到、也最让人困惑的 JSON 错误。本指南讲清楚每个错误是什么意思、为什么会出现,以及如何修正 JSON 语法让解析器接受它。
「[object Object] is not valid JSON」到底是什么意思?
当 JavaScript 在不调用 JSON.stringify() 的情况下把对象转换为字符串时,结果就是文本 [object Object] —— 这是每个对象 .toString() 方法的默认输出。如果这个字符串接着被传给 JSON.parse(),或作为请求体发送出去,你就会得到这个错误:
SyntaxError: "[object Object]" is not valid JSON
解析器在尝试解析字面字符串 [object Object]。它看到 [,期待一个 JSON 数组,却发现没加引号的词 object,于是失败。这个方括号是真的存在的 —— 它正是字符串 [object Object] 的第一个字符 —— 但接下来的内容不是合法的 JSON 数组语法。
为什么 [object Object] 会出现在 JSON 里?
根本原因永远是一样的:一个 JavaScript 对象在被解析或传输之前,在代码某处被强制转成了字符串。下面是最常见的四种情形:
字符串拼接
当你把一个对象和字符串拼接时,JavaScript 会调用对象上的 .toString(),它返回 [object Object]:
const user = { name: "Alice", age: 30 };
// ❌ 字符串拼接会把对象强制转换
const body = "data=" + user;
console.log(body); // "data=[object Object]"
// ✅ 用 JSON.stringify
const body = "data=" + JSON.stringify(user);
fetch / XMLHttpRequest 的 body 没用 JSON.stringify
把一个普通对象作为 fetch 调用的 body 传过去,会自动被转换成字符串:
const payload = { action: "login", user: "alice" };
// ❌ fetch 会把对象强制转成 "[object Object]"
fetch('/api/login', {
method: 'POST',
body: payload,
});
// ✅ 先序列化,设置 Content-Type
fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
模板字面量
直接把对象嵌进模板字面量里会调用 .toString():
const config = { theme: "dark", lang: "en" };
// ❌ 模板字面量强制转换
const json = `{"config": ${config}}`;
// '{"config": [object Object]}' ← 非法 JSON
// ✅ 只对对象本身序列化
const json = `{"config": ${JSON.stringify(config)}}`;
// '{"config": {"theme":"dark","lang":"en"}}'
嵌套 stringify
在一个已经包含「预先序列化过的 JSON 字符串」作为值的对象上调用 JSON.stringify() 会产出双重编码的输出 —— 出现在 JSON 里的是字符串字面量,而不是它所代表的对象:
const inner = JSON.stringify({ id: 1 }); // '{"id":1}'
const outer = JSON.stringify({ data: inner });
// '{"data":"{\"id\":1}"}' —— data 字段是字符串,不是对象
// 如果之后对外层字符串再 JSON.parse(),且想把 data 再当 JSON 用,
// 你得对 result.data 再 JSON.parse() 一次。
如何修复 [object Object] JSON 错误
修复办法永远是:在对象被当作字符串使用或通过网络传输之前,确保用 JSON.stringify() 序列化它。一个快速诊断:在代码里搜出所有把出问题的变量当成字符串使用的地方,然后在那里加上 JSON.stringify()。
// 系统化的修复模式
function toJsonBody(obj) {
if (typeof obj === 'string') {
// 已经是字符串 —— 在使用之前先校验它是合法 JSON
JSON.parse(obj); // 不合法就抛错
return obj;
}
return JSON.stringify(obj);
}
「Expected a JSON Object, Array or Literal」是什么意思
这个错误来自 Firefox 自带的 JSON 查看器(以及一些 JSON 校验器),意思是你的 JSON 顶层值不是六种合法 JSON 类型中的任何一种。常见原因:
- 输入是空字符串。
JSON.parse("")会抛这个错,因为空字符串不是合法 JSON 值。 - 输入是
undefined。JSON.stringify(undefined)返回undefined(不是字符串"undefined"),并且JSON.parse(undefined)会抛错。 - 响应是 HTML,而不是 JSON。 服务端错误页常常返回 HTML。第一个字符
<不是合法 JSON。在认定 JSON 本身坏掉之前,先在 Network 面板检查Content-Type头和响应原文。 - 文件开头有 BOM。 加在 JSON 文件前面的 UTF-8 BOM(字节
0xEF 0xBB 0xBF)会让严格的解析器抛这个错。RFC 8259 明确禁止 JSON 中出现 BOM。
// 解析前对空/undefined 加保护
function safeParse(text) {
if (!text || typeof text !== 'string') {
throw new TypeError(`Cannot parse ${typeof text} as JSON`);
}
return JSON.parse(text.trimStart()); // trimStart 顺手去掉意外的 BOM/空白
}
JSON 最后一项之后的逗号:尾随逗号错误
另一个极其常见的 JSON 语法错误是尾随逗号 —— 出现在对象或数组最后一项之后的那个逗号:
// ❌ 对象里的尾随逗号
{
"name": "Alice",
"age": 30,
}
// ❌ 数组里的尾随逗号
["red", "green", "blue",]
JSON 语法要求逗号是用来分隔两个项的 —— 它两侧必须各有一个值。后面没有内容的逗号违反了这条文法。JavaScript 自己(自 ES5 起)是允许尾随逗号的,这就是为什么开发者经常不假思索地写上去。
想用程序找出并修复尾随逗号:
// ⚠️ 正则修复 —— 简单情形可用,可能破坏字符串内容
const fixed = raw.replace(/,\s*([}\]])/g, '$1');
// ✅ 更好:用懂语法的修复解析器
// 比如 npm 上的 json-repair 库
想深入了解这个具体错误,请看 JSON 中的尾随逗号:为什么会抛错以及如何修复。
如何修正 JSON 语法:完整核对清单
在伸手去拿 JSON 修正工具之前,先按这份清单走一遍,看看是哪一类错误:
结构
- 每个
{都有匹配的},每个[都有匹配的]。没闭合的括号是最常见的截断错误之一。 - 没有尾随逗号 —— 对象的最后一个键值对、或数组的最后一项后面都不能有逗号。
- 没有缺失的逗号 —— 对象或数组里除最后一项以外的每一项后面都必须跟一个逗号。
字符串
- 所有字符串使用双引号。 单引号字符串(
'Alice')是 JavaScript 语法,不是 JSON。 - 所有对象键都是双引号字符串。 裸键(
{ name: "Alice" })是 JavaScript 对象字面量语法,不是 JSON。 - 字符串中的控制字符要转义。 字符串里的原始换行、制表符和 NUL 字节都是非法的 —— 改用
\n、\t、�之类的转义。
值
- 布尔值是小写:
true/false,不是True/False/TRUE。 - Null 是小写:
null,不是None、nil或NULL。 - 没有
undefined。 JSON 里没有 undefined 类型;请用null或者直接省略这个键。 - 没有
NaN或Infinity。 这些 JavaScript 值在 JSON 中没有对应表示。JSON.stringify({x: Infinity})会悄无声息地产出{"x":null}。
多余内容
- 没有注释。
// 行注释和/* 块注释 */都不是 JSON 规范的一部分。 - 没有尾随内容。 合法的 JSON 文本是且只有一个值 —— 它前面除了可选的空白外别无他物,后面也不能有任何东西。
使用 JSON 修正工具:什么时候自动化
对一次性调试,手工修 JSON 很快。但对那些要从外部来源(API、AI 模型输出、用户输入)接收 JSON 的生产管道,你需要一个 JSON 修正器:能用代码或工具自动修复常见语法错误,且不会破坏合法内容。
一个好的 JSON 修正器会处理:
- 对象和数组里的尾随逗号
- 单引号字符串 → 双引号字符串
- 未加引号的键 → 加双引号的键
- Python 字面量(
True、False、None)→ JSON 对应值 - JavaScript 的
// 行和/* 块 */注释 → 删除 - Markdown 代码围栏(
json ...)→ 剥掉 - 未闭合的括号 → 自动补上
关键要求是修正过程要懂语法 —— 工具要知道哪些 token 是结构分隔符、哪些是在字符串值内部,这样它永远不会误改恰好含有 ,} 或 True 的字符串内容。
想看 JavaScript 代码里如何实现 JSON 修复的完整走查,请看 如何在 JavaScript 中处理损坏的 JSON。
避免 JSON.stringify 的坑(包括循环引用)
一旦你养成总是用 JSON.stringify 序列化的习惯,还有两种情况会绊住人:
- 循环引用会抛错。 类似
const a = {}; a.self = a;的值会给你TypeError: Converting circular structure to JSON。三个好替代:用一个跟踪已访问对象的自定义replacer丢掉反向引用;在内存中深拷贝时改用structuredClone(value);当你确实需要序列化一个含环的图并在之后重建时,可以用flatted这样的库。 - 有损类型。
JSON.stringify会默默丢掉undefined、函数和Symbol值,并把NaN/Infinity转成null。请在 stringify 之前 把它们转换成可表示的内容,而不是在解析之后。
速查:常见 JSON 错误与修复
// 1. [object Object] —— 对象被强转成字符串
❌ fetch(url, { body: myObject })
✅ fetch(url, { body: JSON.stringify(myObject) })
// 2. 尾随逗号
❌ { "a": 1, "b": 2, }
✅ { "a": 1, "b": 2 }
// 3. 单引号
❌ { 'name': 'Alice' }
✅ { "name": "Alice" }
// 4. 未加引号的键
❌ { name: "Alice" }
✅ { "name": "Alice" }
// 5. Python 布尔
❌ { "active": True }
✅ { "active": true }
// 6. JSON 中的注释
❌ { "debug": true // log everything }
✅ { "debug": true }
// 7. 空字符串
❌ JSON.parse("")
✅ JSON.parse(text || "null")
// 8. 把 HTML 错误页当作「JSON」
❌ JSON.parse("<!DOCTYPE html>...")
✅ 在调用 response.json() 前先检查 response.ok 与 Content-Type
常见问题
「[object Object] is not valid JSON」是什么意思?
一个 JavaScript 对象被默认的 .toString() 转换成了字符串,产生字面文本 [object Object],而这段文本接着被当成 JSON 去解析或发送。修复办法是:在把这个值当作字符串使用之前,先用 JSON.stringify() 序列化它。
fetch 请求里怎么修这个 [object Object] 错误?
把 body 设置为 body: JSON.stringify(payload),并加上 Content-Type: application/json 头。把裸对象作为 body 传过去会被强制转成 [object Object]。
「Expected a JSON object, array or literal」是什么意思?
当顶层值不是六种 JSON 类型之一时,Firefox 与一些校验器会打印这个 —— 通常是因为输入是空、undefined、是 HTML 而不是 JSON,或者以 BOM 开头。先查 response.ok 和 Content-Type 头。
最常见的 JSON 语法错误有哪些?
尾随逗号、单引号、未加引号的键、Python 字面量(True/None)、注释,以及 NaN/Infinity。每个都有专门指南:见 尾随逗号、unexpected-token 错误、unexpected end of input,以及 非法控制字符。
在线修复 JSON 语法 —— 无需任何安装
如果你现在就有一段需要修正的损坏 JSON,JSON Fix 会自动修复上述所有错误。粘贴你的 JSON —— 不论多损 —— 点 Repair & Format,就能拿回语法正确、格式化好的 JSON。工具完全在你的浏览器里运行:没有任何数据被发送到服务器,所以处理敏感负载也安全。
- JSON Fix —— 即时修复并格式化损坏的 JSON
- 如何在 JavaScript 中处理损坏的 JSON —— 把优雅的 JSON 修复加进自己的应用代码
- Unexpected Token o in JSON at Position 1 —— [object Object] 错误的近亲
- 什么是 JSON? —— JSON 格式、语法与数据类型的完整指南
- JSON Diff —— 对比原始与修正后的 JSON,核实你的修复是否准确