先看报错本身

JSON 解析失败的报错信息通常长这样:

SyntaxError: Unexpected token '<' in JSON at position 0
SyntaxError: Unexpected end of JSON input

很多人看到就懵了。其实报错里的 token 类型和 position 已经指明了病因,按下面五类对号入座就行。

一、Unexpected token '<' —— 其实是收到了 HTML

这是最常见的一种。position 0 上是个 <,说明你拿到的根本不是 JSON,而是一个网页

常见原因:

  • 接口地址写错了,请求打到了 404 页面
  • 服务端 500 了,返回的是错误页
  • 接口需要登录,被重定向到了登录页
  • 请求经过代理或公共 WiFi,被插入了认证页面
  • 反过来:接口正常,但响应头 Content-Type 不是 application/json,前端用错了方式解析

怎么查:打开浏览器 DevTools 的 Network 面板,找到这个请求,点开 Response 看原始内容。如果开头是 <!DOCTYPE html> 或者 <html,就确认了。

怎么修:解析之前先校验响应,别直接 JSON.parse

jsconst res = await fetch(url)
if (!res.ok) throw new Error(`HTTP ${res.status}`)

const text = await res.text()
if (text.trimStart().startsWith('<')) {
  throw new Error('接口返回了 HTML 而不是 JSON,检查地址和登录态:' + text.slice(0, 100))
}
const data = JSON.parse(text)

先读成文本再解析,出错时还能把原始响应打出来,比直接 parse 好排查得多。

二、Unexpected end of JSON input —— 响应被截断

意思是 JSON 还没结束就没了。常见于:

  • 响应体是空的(接口成功但没返回内容)
  • 服务端超时或崩溃,连接中断
  • 流式响应没有读完就解析
  • 内容太长被中间的网关截断

怎么查:看响应长度是不是 0,或者比预期短很多。也检查一下服务端日志有没有异常。

怎么修:解析前先判断内容非空。

jsif (!text || !text.trim()) {
  throw new Error('响应为空')
}

三、Unexpected token '}' 或 ']' —— 逗号引号的问题

JSON 的语法比 JavaScript 对象字面量严格得多,最常见的三处差异:

尾逗号。JavaScript 里允许,JSON 不允许:

js// 合法 JS,但非法 JSON
{ "a": 1, "b": 2, }

单引号。JSON 只认双引号:

js{ 'a': 1 }   // 非法,必须写成 { "a": 1 }

字符串里有未转义的特殊字符。反斜杠、双引号、换行都要转义:

js{ "path": "C:\\Users\\test" }   // 反斜杠要写成 \\

四、看不见的字符:BOM 头

Windows 上特别常见。记事本、PowerShell 的 Out-File 默认会在文件开头写入一个不可见的 BOM(字节序列 EF BB BF)。

现象很迷惑:报错位置那个 token 看起来是空的,或者显示成一个乱码方块。

怎么确认:用十六进制查看文件开头,或者用工具检查。

怎么修:Node.js 里可以这样剥掉:

jsconst text = fs.readFileSync(path, 'utf8').replace(/^\uFEFF/, '')

怎么避免:编辑器里把编码设成「UTF-8 无 BOM」,PowerShell 用 -Encoding utf8NoBOM

五、不报错但数据变了:大整数精度丢失

这一类不会抛异常,但更危险——数字悄悄被改掉了。

JavaScript 的 Number 是双精度浮点,能精确表示的整数上限是 2^53 - 1。超过这个范围的 ID(比如雪花算法生成的、或者某些平台的订单号)用 JSON.parse 之后末几位会变成 0

jsJSON.parse('{"id": 1234567890123456789}')
// => { id: 1234567890123456800 }   ← 精度已经丢了

怎么修:让后端把大整数用字符串返回,或者用 JSON.parsereviver 配合 BigInt 处理。这个问题值得单独展开,见 → JSON 大整数精度

快速定位是哪种

拿不准的时候,把内容粘到 JSON 格式化 里过一遍,它会指出具体在哪一行、哪个位置出错,比对着报错数字数位置快得多。

如果只是想确认一段内容是不是合法 JSON,JSON 格式化的校验模式也能直接给结论。

小结

报错 病因
Unexpected token '<' 收到了 HTML,不是 JSON
Unexpected end of JSON input 响应为空或被截断
Unexpected token '}' / ']' 尾逗号、单引号、未转义字符
token 是空白/乱码 BOM 头
不报错但数字变了 大整数精度丢失