Skip to content
JSON 工具2026-08-297 分钟阅读

Unexpected token } in JSON at position 247

这段报错几乎每个开发者都见过,但它只告诉你"第 247 个字符附近有问题",不说是什么问题。而 JSON 的报错又特别不直观——真正出错的地方,往往在报错位置的前面几十个字符。

本手册按症状组织,帮你先定位问题类别,再跳到对应的修复方案。每类问题都有详细的专项文章,这里只给你判断路径和最小修复动作。

先按症状定位(诊断表)

| 你看到的现象 | 最可能的原因 | 跳到 | |---|---|---| | Unexpected token <Unexpected token o | 收到的不是 JSON(是 HTML 错误页 / undefined) | 第一类 | | Unexpected token } / ] / , | 尾随逗号、多余括号 | 第一类 | | Unexpected end of JSON input | 数据被截断、空字符串 | 第一类 | | 中文变成 中文 转义 | 序列化时启用了 ASCII 转义 | 第二类 | | 中文显示为 ????é”± | 编码不一致(UTF-8 vs GBK) | 第二类 | | is not valid JSON / Schema 校验失败 | 缺必填字段、类型不符 | 第三类 | | 两份 JSON 看着一样却判定不同 | 键顺序、空白、数字精度 | 第四类 |

判断不了?直接把内容粘进 JSON 格式化工具,它会高亮第一个语法错误的位置——比读报错信息快得多。


第一类:语法错误(JSON.parse 直接报错)

JSON 的语法比 JavaScript 对象字面量严格得多,这是绝大多数报错的根源。

严格性对照表

| 写法 | JavaScript | JSON | 说明 | |---|---|---|---| | 键加引号 | 可省略 | 必须双引号 | {name:"a"} 非法 | | 字符串引号 | 单双引号都行 | 只能双引号 | {'a':1} 非法 | | 尾随逗号 | 允许 | 禁止 | {"a":1,} 非法 | | 注释 | 允许 | 不支持 | ///* */ 都会报错 | | undefined / NaN | 允许 | 不是合法值 | 只能用 null | | 函数、日期对象 | 允许 | 不支持 | 日期只能写成字符串 |

三个高频陷阱

陷阱 1:服务端返回的不是 JSON

SyntaxError: Unexpected token < in JSON at position 0

position 0 就出错,几乎总是因为响应体是 HTML 错误页(以 < 开头)或纯文本。常见于:接口 404/500、登录态失效被重定向到登录页、网关返回了错误页。

排查:在 JSON.parse() 之前先打印原始响应体看一眼,别直接解析。

陷阱 2:BOM 头

带 UTF-8 BOM 的 JSON 会在开头多一个不可见字符 \uFEFF,导致 Unexpected token 

# 检查文件是否带 BOM
head -c 3 file.json | xxd | head -1   # 出现 efbbbf 即为 BOM

陷阱 3:数据被截断

Unexpected end of JSON input 通常意味着:字符串为空、null、或传输中被截断(大响应体超时、流式读取没读完)。

👉 完整的报错清单与逐条修复,见 JSON.parse Unexpected token 完全修复指南


第二类:中文与编码问题

这类问题最迷惑人,因为数据在语法上完全合法,只是"看起来不对"。

症状 A:中文变成 \uXXXX

{"name":"\u5f20\u4e09"}

这不是错误,是 Unicode 转义——JSON 标准允许的合法表示,解析后会还原成"张三"。之所以出现,通常是序列化时设置了 ensure_ascii=True(Python)或类似选项。

如果你希望文件里直接显示中文,处理方式:

# Python:关闭 ASCII 转义
json.dumps(data, ensure_ascii=False)
// JavaScript:JSON.stringify 默认不转义中文,无需处理
JSON.stringify({name: "张三"})  // {"name":"张三"}

👉 详见 JSON 中文变 \uXXXX 转义怎么办

症状 B:中文乱码(????é”±

这是字符编码不一致导致的,和 JSON 语法无关:

| 乱码形态 | 原因 | |---|---| | ???? | 写入时编码不支持中文(如 ASCII、Latin-1) | | é”± | UTF-8 字节被按 GBK 解读 | | 锟斤拷 | UTF-8 被错误转成 GBK 再转回,已不可逆 |

黄金法则:JSON 标准规定默认编码是 UTF-8。读写两端都用 UTF-8,乱码就不会出现。

# 检查文件实际编码
file -I data.json
# 转换 GBK -> UTF-8
iconv -f GBK -t UTF-8 data.json > data.utf8.json

第三类:数据结构与 Schema 校验失败

语法合法,但结构不符合预期。

常见校验失败原因

| 报错 | 原因 | |---|---| | is a required property | 缺必填字段 | | is not of a type 'string' | 字段类型不符(数字写成了字符串等) | | additionalProperties not allowed | 出现了 Schema 未定义的字段 | | does not match pattern | 不符合正则约束 |

易踩点:数字 1 和字符串 "1" 在 JSON 里是不同类型。接口返回的 "age": "30" 会让期望 integer 的 Schema 校验失败。

排查方法:先用 JSON Schema 校验器 拿到完整错误列表(它会列出所有问题,而不是只报第一个)。

👉 详见 JSON Schema required / 类型校验失败怎么办


第四类:数据差异与比对

两份 JSON"看起来一样"但程序判定不同,通常因为:

  1. 键顺序不同 —— JSON 对象在语义上无序,但字符串比较时顺序不同就不相等。
  2. 空白与缩进不同 —— 序列化后的格式差异。
  3. 数字精度 —— 0.1 + 0.2 !== 0.3 这类浮点问题,或大整数超过 IEEE 754 安全范围。
  4. 数组顺序 —— 数组是有序的,顺序不同即语义不同。

正确做法:做语义比对(解析后递归比较),而不是字符串比对。用 JSON Diff 工具 可以直观看到两棵树的差异节点。


通用排查流程(适用于任何 JSON 问题)

遇到看不懂的 JSON 报错,按这四步走,能解决绝大多数情况:

1. 先看原始字节,而不是解析后的结果JSON.parse() 前把原始字符串打印出来。很多"JSON 错误"其实根本不是 JSON(HTML 错误页、空响应、被截断的流)。

2. 用工具定位第一个错误位置 把内容粘进 JSON 格式化工具。语法错误会被高亮并指出行列——注意真正的错误通常在报错位置之前(比如少了一个引号,报错会在下一个符号处才暴露)。

3. 二分法缩小范围 对大文件,把 JSON 对半砍,分别验证哪一半能解析。重复几次就能定位到出问题的字段。

# 命令行快速验证
python3 -m json.tool data.json > /dev/null && echo "JSON 合法" || echo "JSON 非法"
# 或
jq . data.json > /dev/null && echo "JSON 合法"

4. 验证修复后重新校验 语法通过后,如果接口仍报错,问题就在结构而非语法——转到 Schema 校验。


排错工具箱

| 用途 | 工具 | |---|---| | 格式化 / 高亮语法错误 | JSON 格式化 | | 对比两份 JSON 差异 | JSON Diff | | 校验结构是否符合 Schema | JSON Schema 校验器 | | 从大 JSON 中提取字段 | JSONPath 查询 | | JSON 转 Java / Go / TS 实体类 | 转 Java · 转 Go |

以上工具全部在浏览器本地运行,你可以放心把生产环境的 JSON 粘进去——数据不会离开你的机器。按 F12 打开 Network 面板就能验证。


常见问题

Q:报错指向的位置,为什么往往不是真正出错的地方? 因为解析器是"读到某个字符才发现前面不对"。比如 {a:1}a 没加引号,解析器要到冒号或后续符号才判定异常。所以报错位置是异常暴露点,真正的问题在它之前。

Q:JSON.parse 成功但数据不对,可能是什么原因? 语法通过不代表语义正确。常见:数字被写成了字符串、嵌套层级错了、数组被序列化成了对象、大整数精度丢失。这类问题要靠 Schema 校验或 Diff 比对发现。

Q:超大 JSON(几百 MB)怎么排错? 浏览器工具有内存上限。建议命令行:jq 做流式解析和定位,python3 -m json.tool 做格式验证。先用 jq 'keys' 看顶层结构,再逐层下钻。

Q:如何避免 JSON 问题反复出现? 在 CI 里加一道校验:接口响应体用 Schema 校验 + 快照 Diff。能在合并前拦住绝大多数结构变更。

小结

JSON 排错的核心思路是先分类,再下钻

  1. 语法错误 → 看报错位置之前,重点查引号、逗号、注释
  2. 中文问题 → 区分是 Unicode 转义(合法)还是编码乱码(编码不一致)
  3. 结构问题 → 用 Schema 校验器拿完整错误列表
  4. 差异问题 → 做语义比对,不要比字符串

把这份手册存下来,下次遇到 Unexpected token 时按诊断表对号入座,比逐字符数位置快得多。


广告