CodeKitHub
简体中文
JSON.parse 报 Unexpected token 怎么办?7种常见原因逐一排查

JSON.parse 报 Unexpected token 怎么办?7种常见原因逐一排查

发布于 2026年7月23日

SyntaxError: Unexpected token X in JSON at position N 是JavaScript里最常见的报错之一,但信息量很低——它只告诉你解析器在哪个位置放弃了,不会告诉你为什么。这篇讲清楚怎么真正定位并修复。

第一步:读懂那个position数字

JSON.parse 从字符串开头第0个字符开始计数。如果这段JSON是从变量里来的,先把报错位置附近的原文打印出来看一眼,再做别的:

try {
  JSON.parse(raw);
} catch (e) {
  const match = e.message.match(/position (\d+)/);
  if (match) {
    const pos = Number(match[1]);
    console.log(raw.slice(Math.max(0, pos - 20), pos + 20));
  }
}

这一段代码能解决的问题比任何“JSON语法讲解”都多,因为大部分“unexpected token”报错的真正原因是“你根本不知道这个字符串里实际有什么”——复制粘贴带来的多余空格、模板字符串里多出来的换行符、或者文件开头藏着的字节顺序标记(BOM,大多数编辑器里完全看不见)。

7种原因,按实际出现频率排序

  1. 多余的尾随逗号。 {"a": 1, "b": 2,} ——在JS对象字面量里合法,在JSON里不合法。}]前面多一个逗号是最常见的原因,没有之一。
  2. 用单引号代替双引号。 {'a': 1} 是JS写法,不是JSON。JSON里键名和字符串值都必须用双引号,没有例外。
  3. 键名没加引号。 {a: 1} ——同样,JS里合法,JSON里不合法。每个键都要加引号。
  4. 用了JSON里不存在的JS值。 undefinedNaN、函数、或者注释(// 像这样)——这些东西JSON规范里压根不存在,只在JavaScript里存在。
  5. 重复编码。 你调用了两次JSON.stringify(),或者你正在解析一个其实已经是对象的字符串——调用.parse()前先用typeof raw === 'string'检查一下。
  6. 空字符串或undefined响应。 如果fetch静默失败或返回空body,JSON.parse("")会报Unexpected end of JSON input(一个相关但不同的报错)——解析前先检查response.ok并打印原始body。
  7. 复制粘贴带来的BOM或不可见字符。 从PDF、Word文档或某些终端输出里复制JSON,可能带着BOM或不间断空格,肉眼看起来和普通字符一模一样。

最快的修法:先校验,再debug

一个字符一个字符去读报错信息太慢了。把整段字符串粘贴到能直接高亮出非法字符的格式化工具里,而不是根据一个位置数字瞎猜——这样“大概812个字符附近出了问题”就变成了“就是这里缺了个括号”。(工具链接见下方。)

JSON本身没问题但还是报错的情况

如果格式化工具确认你的JSON语法完全正确,但JSON.parse还是报错,那说明你传进去的字符串根本不是你以为的那个字符串。最常见的原因:对一个Response对象直接调用了.parse(),而不是它解析后的body。

// 错误写法——解析的是 "[object Response]",不是body内容
const data = JSON.parse(await fetch(url));

// 正确写法
const data = await (await fetch(url)).json();
// 如果需要先拿原始文本:
const text = await (await fetch(url)).text();
const data = JSON.parse(text);

速查表

报错现象 大概率原因
Unexpected token } 闭合大括号前多了个逗号
Unexpected token ' 用了单引号而不是双引号
Unexpected token a(或任意字母) 对象键名没加引号
Unexpected end of JSON input 空字符串、响应被截断、或括号没闭合
Unexpected token (position 0) 复制粘贴或Windows保存文件带来的字节顺序标记

这些都不需要死记硬背——修法永远是同一套三步走:打印报错位置附近的原文、丢进格式化工具跑一遍、按它标出来的那一个字符改。

← 返回博客