← 全部文章

修复 “[object Object] is Not Valid JSON” 与其他 JSON 语法错误

遇到 “[object Object] is not valid JSON” 或 “expected a JSON object, array or literal”?学会这些错误的成因、如何修正 JSON 语法、修复尾随逗号,以及自动修复损坏的 JSON。

你跑了代码、看了 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 nilNULL
  • 没有 undefined JSON 里没有 undefined 类型;请用 null 或者直接省略这个键。
  • 没有 NaNInfinity 这些 JavaScript 值在 JSON 中没有对应表示。JSON.stringify({x: Infinity}) 会悄无声息地产出 {"x":null}

多余内容

  • 没有注释。// 行注释 /* 块注释 */ 都不是 JSON 规范的一部分。
  • 没有尾随内容。 合法的 JSON 文本是且只有一个值 —— 它前面除了可选的空白外别无他物,后面也不能有任何东西。

使用 JSON 修正工具:什么时候自动化

对一次性调试,手工修 JSON 很快。但对那些要从外部来源(API、AI 模型输出、用户输入)接收 JSON 的生产管道,你需要一个 JSON 修正器:能用代码或工具自动修复常见语法错误,且不会破坏合法内容。

一个好的 JSON 修正器会处理:

  • 对象和数组里的尾随逗号
  • 单引号字符串 → 双引号字符串
  • 未加引号的键 → 加双引号的键
  • Python 字面量(TrueFalseNone)→ 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.okContent-Type 头。

最常见的 JSON 语法错误有哪些?

尾随逗号、单引号、未加引号的键、Python 字面量(True/None)、注释,以及 NaN/Infinity。每个都有专门指南:见 尾随逗号unexpected-token 错误unexpected end of input,以及 非法控制字符

在线修复 JSON 语法 —— 无需任何安装

如果你现在就有一段需要修正的损坏 JSON,JSON Fix 会自动修复上述所有错误。粘贴你的 JSON —— 不论多损 —— 点 Repair & Format,就能拿回语法正确、格式化好的 JSON。工具完全在你的浏览器里运行:没有任何数据被发送到服务器,所以处理敏感负载也安全。