你跑了代码、看了 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、