JSON 解析错误排查:Unexpected token、尾逗号、引号和大整数

JSON.parse() 很严格。严格是数据交换的优点,但也意味着 JavaScript 对象字面量、日志里的“类 JSON”、和真正合法 JSON 之间的小差异,都会导致解析失败。

最常见的 JSON 解析错误来自:

  • 尾逗号
  • 单引号
  • key 没有双引号
  • 注释
  • 复制了日志前缀
  • 字符串转义错误
  • 接口返回的是 HTML 或纯文本,不是 JSON
  • 大整数解析后丢失精度

JSON 不是 JavaScript 对象字面量

下面是合法 JavaScript,但不是合法 JSON:

{
  name: 'Ada',
  active: true,
}

合法 JSON 必须使用双引号包住 key 和字符串,并且不能有尾逗号:

{
  "name": "Ada",
  "active": true
}

如果浏览器控制台、文档或后端日志里展示的“JSON”带单引号或未加引号的 key,在严格解析前都应该当作类 JSON 文本。

常见 Unexpected token 原因

Unexpected token 表示解析器在某个位置遇到了不该出现的字符。

{"name": "Ada",}

"Ada" 后面的尾逗号非法。

{'name': 'Ada'}

单引号非法。

{name: "Ada"}

对象 key 必须使用双引号。

{
  "name": "Ada" // user name
}

JSON 里不能有注释。

先确认响应真的是 JSON

API 调用出现 JSON parse error 时,先看原始响应,不要先改解析代码。

常见意外情况:

  • 服务端返回了 HTML 错误页
  • 代理返回了登录页
  • 接口返回 204 No Content,body 为空
  • 后端在 JSON 前输出了 warning
  • 响应被压缩或编码方式异常

前端可以临时这样调试:

const text = await response.text()
console.log(text)
const data = JSON.parse(text)

如果第一个字符是 <,你很可能在解析 HTML。如果开头是 Warning: 或堆栈信息,应先修服务端输出。

先验证,再格式化

格式化工具能让合法 JSON 更易读,但不能在没有假设的情况下安全格式化非法 JSON。

用 JSON 工具定位:

  • 第一个非法字符
  • 错误行列
  • 括号是否匹配
  • 字符串转义是否正确
  • 属性之间是否缺逗号

然后修源数据。不要依赖格式化工具自动“修复”生产 payload,除非你清楚它改了什么。

正确处理转义字符

JSON 字符串里,反斜杠是转义字符。

合法:

{
  "path": "C:\\\\Users\\\\Ada",
  "quote": "She said \\\"hello\\\""
}

非法:

{
  "path": "C:\Users\Ada"
}

如果数据来自某种编程语言的字符串字面量,要注意可能有两层转义:语言字符串一层,JSON 字符串一层。

大整数可能丢精度

JSON 支持数字,但 JavaScript 会把它解析成 Number。非常大的整数可能丢失精度。

有风险:

{
  "order_id": 12345678901234567890
}

更稳:

{
  "order_id": "12345678901234567890"
}

订单号、支付流水、数据库主键这类超过 JavaScript 安全整数范围的 ID,通常应该序列化为字符串。

排错清单

JSON 解析失败时:

  1. 复制原始响应或文件内容。
  2. 确认开头是 {["、数字、truefalsenull
  3. 检查是否是 HTML、日志前缀、warning 或空响应。
  4. 删除尾逗号和注释。
  5. 只在确定是字符串时,把单引号改成双引号。
  6. 检查字符串里的转义。
  7. 大整数 ID 改用字符串。

相关工具

JSON 格式化工具 校验和格式化 payload。如果 JSON 里包含 URL 字段,先用 URL 编码解码工具 处理;如果包含 Base64 字段,单独用 Base64 工具 解码,不要直接判断整个 API 响应坏了。