Unexpected token报错:原因、定位与修复
JSON解析时看到Unexpected token,通常不是这个字符本身有问题,而是它前面的引号、逗号、括号,或者数据来源出了问题。本文按报错里的关键字逐个拆解,并给出可直接复制的修复示例。
本文覆盖:Unexpected token in JSON、Unexpected token < in JSON at position 0、Unexpected token o in JSON at position 1、Unexpected token u in JSON at position 0、Unexpected token ' in JSON等常见变体。
30秒判断
| 报错里的关键字 | 大概率原因 |
|---|---|
< | 接口返回了HTML或XML,不是JSON |
[object Object] | 传入了已经解析过的对象 |
undefined | 传入了undefined |
' | 用了单引号 |
]、}、, | 尾随逗号、缺少逗号或括号不匹配 |
| 不可见字符 | 文件带BOM |
最快修复
- 把原始JSON和完整报错粘贴到JSON校验工具。
- 工具会标出错误所在的行和列。先检查报错位置前1至2行。
- 如果是尾随逗号、单引号、注释、BOM等常见问题,点“修复”。否则按下面的关键字对照表排查。
本站数据在浏览器本地处理,不上传服务器。修复需要手动点击,不会自动改你的数据。
先看懂报错:position、行号列号和新旧文案
JSON解析器会逐个字符读取输入。遇到不符合语法的字符时,解析器抛出Unexpected token。报错里的position是解析器失败的位置,真正的原因常常在它前面1至2行。
V8是Chrome、Edge、Node.js使用的JavaScript引擎。JSON.parse的报错文案在不同版本中改过,下面两种写法都可能出现。
| 场景 | 较早的Chrome/Node | 较新的Chrome/Node |
|---|---|---|
| 单引号 | Unexpected token ' in JSON at position 14 |
Unexpected token ''', ... is not valid JSON |
| HTML响应 | Unexpected token < in JSON at position 0 |
Unexpected token '<', "<!DOCTYPE html>..." is not valid JSON |
| 传入对象 | Unexpected token o in JSON at position 1 |
"[object Object]" is not valid JSON |
| 传入undefined | Unexpected token u in JSON at position 0 |
"undefined" is not valid JSON |
| 对象尾随逗号 | Unexpected token }(旧版常见) |
Expected double-quoted property name in JSON at position 53 (line 5 column 1) |
表中的位置和行列以实际输入为准。单引号在键名位置时,较新V8通常报Expected property name or '}';在值位置时报Unexpected token '''。Firefox和Safari的报错文案不同,但原因和修复方法相同。
按报错关键字查原因
先按报错里出现的关键字分流,再进入下面的详细原因。新旧文案都能用这张表。
| 报错关键字 | 常见原因 | 最小示例 | 修复 |
|---|---|---|---|
< |
服务端返回HTML或XML | <!DOCTYPE html> |
查状态码、Content-Type、接口地址、登录跳转、代理 |
[object Object] |
传入对象 | JSON.parse({a:1}) |
直接使用对象,需要字符串用JSON.stringify |
undefined |
传入undefined | JSON.parse(undefined) |
检查变量、响应体、localStorage |
' |
单引号 | {'a':1} |
改成双引号,或用修复 |
Expected property name or '}' |
单引号键名、注释、未加引号的key | {'a':1} |
改双引号、删注释、给key加引号 |
Expected double-quoted property name |
对象尾随逗号 | {"a":1,} |
删除最后一个逗号 |
]、}、, |
尾随逗号、缺逗号、括号不匹配 | {"a":[1,2} |
删除多余逗号或补齐括号 |
| 不可见字符 | BOM | \uFEFF{"a":1} |
另存为无BOM,或使用replace(/^\uFEFF/,'') |
\ |
非法转义 | {"path":"C:\Users"} |
双反斜杠C:\\Users |
NaN、Infinity |
非法数字 | {"n":NaN} |
用null或字符串 |
@、= |
Java toString等非JSON文本 | User@hash{id=1} |
先转标准JSON,当前一键修复不处理 |
五种最高频原因与修复
Unexpected token <:接口返回了HTML
这是最常见、也最容易误判的一种。<不是JSON里的字符,它通常意味着你拿到的是一个HTML页面。
Unexpected token '<', "<!DOCTYPE html>..." is not valid JSON
最小复现:
const res = await fetch('/api/user');
const data = await res.json();
先别改JSON,先看请求:
const res = await fetch('/api/user');
const raw = await res.text();
console.log(res.status);
console.log(res.headers.get('content-type'));
console.log(raw.slice(0, 200));
常见原因:
- 接口地址写错,命中了前端路由,返回
index.html。 - 登录态失效,被重定向到登录页。
- 后端返回500,响应体是HTML错误页。
- Nginx或网关把JSON响应替换成了HTML。
- 本地代理配置错误。
修复:确认status是200,Content-Type包含application/json,再解析。不要把HTML当JSON修。可以先把真实响应粘贴到JSON校验工具,确认它到底是不是JSON。
尾随逗号
最小复现:
{
"name": "Alice",
"age": 30,
"city": "Tokyo",
}
报错通常包含Expected double-quoted property name,较新V8可能带(line 5 column 1)。
修复:删除最后一个逗号。
{
"name": "Alice",
"age": 30,
"city": "Tokyo"
}
也可以直接粘贴到JSON格式化工具,点“修复”。
单引号
最小复现:
{
"name": "Alice",
"city": 'Tokyo'
}
报错通常包含Unexpected token '''。
如果单引号出现在键名位置,较新V8通常报Expected property name or '}'。
修复:JSON只允许双引号。改成双引号,字符串里的撇号需要转义。
{
"name": "Alice",
"city": "Tokyo"
}
单引号、尾随逗号和注释混在一起时,粘贴到JSON格式化工具点“修复”更快。
注释
最小复现:
{
// 用户名
"name": "Alice"
}
报错通常包含Expected property name or '}'。
修复:标准JSON不支持注释。删除注释,或改用YAML、JSONC、JSON5。浏览器原生JSON.parse不接受注释。需要临时处理时,可以粘贴到JSON格式化工具点“修复”。
BOM
最小复现:文件开头有不可见的U+FEFF,十六进制为EF BB BF。
\uFEFF{"name":"Alice"}
报错位置通常在0,较新V8会引用一个看起来像空白的字符。
修复:另存为UTF-8无BOM,或在代码里去掉。
const cleaned = text.replace(/^\uFEFF/, '');
JSON.parse(cleaned);
也可以直接粘贴到JSON格式化工具点“修复”。
其他常见写法
| 场景 | 示例 | 处理 |
|---|---|---|
| 未加引号的key | {name:"Alice"} | 给key加双引号,可用修复 |
| 括号不匹配 | {"a":[1,2} | 补齐]或} |
| 非法转义 | {"path":"C:\Users"} | 使用C:\\Users,或用JSON.stringify生成 |
| NaN或Infinity | {"n":NaN} | 改成null或字符串 |
| 前导零 | {"code":007} | 改成7 |
| Python dict | {'a': True, 'b': None} | 本站修复可转标准JSON |
| Java toString | User@hash{id=1} | 当前一键修复不处理,先转标准JSON |
不是语法错:空响应、截断和类型错误
有些Unexpected token并不是JSON语法问题,而是解析之前的数据就错了。
Unexpected end of JSON input:空字符串、响应被截断、文件没写完。JSON.parse(undefined):传入undefined,报错里可能包含undefined或旧版u。JSON.parse(object):传入对象,报错里包含[object Object]或旧版o。- 服务端返回HTML:报错里包含
<。
安全的解析顺序是先读文本、看状态码,再解析:
const res = await fetch('/api/user');
const raw = await res.text();
if (!res.ok) {
console.error(`HTTP ${res.status}`, raw.slice(0, 200));
} else if (!raw) {
console.error('响应体为空');
} else {
try {
const data = JSON.parse(raw);
} catch (e) {
console.error('JSON解析失败:', e.message, raw.slice(0, 200));
}
}
怎么避免再次出现
- 用
JSON.stringify()生成JSON,不要手拼字符串。 - 解析前先看
response.status和Content-Type。 - 先
response.text(),打印前200个字符,再JSON.parse。 - 编辑器开启JSON校验,CI加一条
python -m json.tool或jq empty。 - 不确定数据来源时,先校验再处理。
本站怎么帮你
- 标出错误所在的行和列。
- 中文提示,不要求读者先理解V8英文文案。
- 一键修复尾随逗号、单引号、注释、未加引号的key、BOM、Python dict、截断JSON。
- 格式化和压缩保留大整数,不会把订单号悄悄改写。
- 数据在浏览器本地处理,不上传服务器。
- 修复需要手动点击,不会自动改用户数据。
常见问题
Unexpected token <是什么意思?
服务端返回了HTML或XML,不是JSON。常见于接口地址写错、登录态失效被重定向、后端500返回错误页、Nginx或网关改写响应。先看Network里的状态码和Content-Type,不要先改JSON。
Unexpected token o怎么解决?
传给JSON.parse的是一个对象,被隐式转成了[object Object]。如果数据已经是对象,直接使用。如果需要字符串,用JSON.stringify。
Unexpected token u怎么解决?
传入了undefined。常见于localStorage.getItem返回null、接口没有响应体、变量名写错。先判断空值,再解析。
Unexpected token '单引号怎么修?
JSON只允许双引号。把单引号换成双引号,字符串里的撇号需要转义。也可以用本站的一键修复。
JSON可以有注释或尾随逗号吗?
标准JSON不允许。JSONC和JSON5允许注释和尾随逗号,但浏览器原生JSON.parse不支持。需要注释时改用YAML或JSONC工具。
为什么本地能解析,线上报错?
线上可能返回了HTML错误页、被网关改写、编码不同或响应被截断。打印response.status、Content-Type和raw.slice(0, 200)再判断。
修复后大数字会变吗?
本站格式化和压缩使用LosslessJSON,保留原数字。修复后仍建议检查关键ID。转XML时大整数可能不保真,长ID建议先作为字符串处理。
本站会上传我的JSON吗?
格式化、校验、修复在浏览器本地执行,不会主动上传输入内容。页面会加载统计脚本,你可以打开Network面板验证请求。输入默认保存在本机localStorage,公共电脑用完点“清空”。