先说结论:JSON 出错就那么几类——引号、逗号、括号、转义,以及从其他语言带来的「长得像」的写法。校验器告诉你*错在哪*、*解析器当时想要什么*;本指南把每种报错原文映射到具体修法。一个诚实的范围说明:YYSI 格式化工具负责校验、定位、格式化、压缩、排序、对比——不自动修复。修复要你自己动手;这更安全,因为改语法的「自动修复」也可能改变含义(想想 007 变成 7)。
报错字典(全部在真实工具中实测)
下表每一条都是把样例粘进真实格式化工具后记录的原文。行列位置来自该工具的解析器;其他工具可能指向不同位置——但*原因*和*修法*两列是通用的。
| 你粘贴的内容 | 解析器的原话(实测) | 含义 → 具体修法 |
|---|---|---|
{'name': 'YYSI'} | 第 1 行第 2 列:Expected object key | JSON 字符串只能用双引号 → "name": "YYSI" |
{"a": 1, "b": 2,} | 第 31 列:Expected object key | 闭括号 } 前的尾逗号——解析器以为还有新键 → 删掉最后一个逗号 |
["news", "tools",] | 第 18 列:Unexpected character "]" | 数组尾逗号 → 删掉 |
{"a": 1 "b": 2} | 第 9 列:Expected "," or "}" | 键值对之间缺逗号 → 补 , |
{"timeout" = 30} | 第 12 列:Expected ":" after key | 赋值写法 → 用 : 不是 = |
{"user": {"name": "Ada"...(少一个 }) | 第 33 列:Expected "," or "}" | 嵌套对象到结尾都没闭合 → 补上缺的 }(如果输入在结构中间直接停止,报错是 Unexpected end of input) |
``json\n{...}\n``(Markdown 围栏) | 第 1 行第 1 列:Unexpected character "`" | 从聊天/大模型窗口复制来的 → 删掉围栏行,只留中间的 JSON |
{"quote": "He said "hi" fast"} | 第 21 列:Expected "," or "}" | 内部引号把字符串提前「结束」了 → 内层引号转义:\"hi\" |
{"text": "line1␊line2"}(真实换行) | 第 16 列:Unescaped control character in string | 字符串里不允许直接换行 → 写成 \n |
{“name”: “YYSI”}(弯引号) | 第 10 列:Unexpected character "“" | 办公软件把直引号替换成弯引号 → 重新输入 ASCII 的 " |
{"delta": +1} | 第 11 列:Unexpected character "+" | JSON 数字不能以 + 开头 → 去掉 |
{"zip": 007} | 第 10 列:Expected "," or "}" | JSON 数字禁止前导零 → 编号类数据请存字符串:"007" |
{"mask": 0x1F} | 第 11 列:Expected "," or "}" | JSON 不支持十六进制 → 写十进制 31 |
{"ok": True, "x": None} | 第 8 列:Unexpected character "T" | Python 字面量 → JSON 用小写 true / false / null |
{"score": NaN} | 第 11 列:Unexpected character "N" | NaN/Infinity 是 JavaScript 的,不是 JSON 的 → 用 null 或真实数字 |
{name: "YYSI"}(键没引号) | 第 2 列:Expected object key | 键必须是带引号的字符串 → {"name": "YYSI"} |
值后面或中间的 // comment | Expected "," or "}"(在中间)/ Unexpected trailing content(在完整文档后面) | JSON 不支持注释 → 把说明移到数据外面 |
| 空输入 | 第 1 行第 1 列:Unexpected end of input | 没内容可解析 → 检查文件是否存成空文件 |
- 复制粘贴版:全部 18 个无效样例(带标签) — 下载样例 · 897 字节
- 机器可读记录:错误文本、修正文本与原因(双语) — 下载样例 · 5650 字节
真实工具里的操作步骤
- 粘贴并看状态. 把文本粘进 格式化工具。输入时实时显示
Valid JSON · N 字节或Invalid JSON。 - 按 Format 定位错误. 无效输入会报告位置和解析器意见,例如 Markdown 围栏是
Error at line 1, column 1: Unexpected character ""`。按行号列号去原文找。 - 对照上面的字典改. 做那个「一个字符」的修复。再按 Format 确认——编辑后位置会变,所以每次先改*第一个*报错,然后重试。
- 格式化 / 压缩 / 排序. 合法后:Format 重新缩进(2 空格 / 4 空格 / Tab),Minify 去掉空白,Sort 在所有层级按字母序排对象键。
- 复制或下载. 复制到剪贴板或下载
yysi-formatted.json。两者只在解析成功后可用。 - 对比两个版本. 把另一份 JSON 粘进对比框按 Diff:逐路径列出改动、新增、删除和数组长度变化——确认你的修复没有动别的东西。
我们的真实对比示例
把 {"model": "flash", "retries": 3, "cache": true, "tools": ["search"]} 与 {"model": "pro", "retries": 3, "cache": false, "tools": ["search", "code"], "note": "nov"} 对比,输出恰好是:
CHANGED $.model "flash" → "pro"
CHANGED $.cache true → false
CHANGED $.tools length 1 → 2
ADDED $.tools[1] "code"
ADDED $.note "nov"严格 JSON 与 JavaScript 对象字面量
大多数「坏 JSON」其实是 JavaScript 对象字面量(或 Python 字典)——另一种语言。JSON(RFC 8259)不允许单引号、不带引号的键、尾逗号、注释、+/十六进制/前导零数字、True/None。编辑器和控制台之所以接受它们,是因为它们执行的是*代码*而不是*数据*。如果文本来自 JS/Python 文件,以上都要转换;如果来自日志,还要预期字符串里未转义的引号和真实换行。
大模型输出是单独一类
- 载荷外面套着 Markdown 围栏(``
或`json)——从聊天窗口复制时最常见;我们的样例在第 1 列复现Unexpected character ""。 - 尾逗号和单引号——模型在模仿训练数据里的 JavaScript。
- 解释字段的注释——模型爱解说,JSON 不接受。
- 修复顺序:删围栏 → 修引号/逗号 → 删注释 → 校验。改完必须把*最终值*重新粘进校验器;没重新解析过的修复不要交付。
007 → 7 把零件号变成了另一个数字;删尾逗号没问题,但删「重复键」是数据决策。要有意识地修复;任何自动修复之后都要核对数字和编号。工具如实提示的边界
| 输入 | 工具行为(实测) | 为什么重要 |
|---|---|---|
{"order_id": 9007199254740993} | 正常解析并格式化,保留原始数字,同时给出警告并指出路径(order_id)——因为该值超过 JavaScript 安全整数范围(2^53−1) | 朴素的解析器会悄悄把 …993 变成 …992;这个警告提醒你下游工具可能正是这么干的 |
{"a": 1, "a": 2}(重复键) | 接受文本;后值覆盖({"a":2})——标准解析器行为,不告警 | 重复键是含糊的数据;如果不是有意写的,请手工去重 |
| 一切合法输入 | Format / Minify / Sort 是纯粹的重新序列化——值、键序(Sort 除外)和数字写法都保持不变 | 格式化不改变含义,排序不改变数值 |
限制
- 格式化工具严格且离线:不修复、不做 schema 校验、不联网。
- 报错位置是该解析器的判断;同一份坏文本,浏览器、Python 或其他工具可能指向不同列——位置当作起点提示,报错类别才是真相。
- 一切在你的浏览器标签页内运行,文本不离开设备。
- 超大输入受浏览器内存限制;多 MB 的载荷请改用本地工具。
相关:要把修好的 JSON 变成表格?用 JSON ↔ CSV 转换器——如果 CSV 在 Excel 里又出问题,看 CSV 中文乱码排查指南。
来源与核查
- RFC 8259 — the JSON grammar this guide checks against (double quotes, no comments, no leading zeros) — 来源核查日期 2026-11-11
- MDN JSON.parse — how the language's own parser differs from JavaScript object literals — 来源核查日期 2026-11-11
来源核查日期 The grammar rules summarized here come from RFC 8259 and MDN (checked 2026-11-11). Every error message, line/column position and behavior in the tables was produced by running the original sample set through the live YYSI JSON formatter's own parser on 2026-11-11 (18 invalid snippets + fixed pairs, plus format/minify/sort/diff/big-number demos). The samples are original synthetic text, published for reuse.
阅读编辑标准(EN),或发送纠错到 [email protected]。