JSON 解析与格式化深度指南:从语法规则到调试技巧

📅 2026年5月5日📂 开发工具⏱️ 约12分钟阅读

JSON 是什么:不只是"带引号的 JavaScript 对象"

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,由 Douglas Crockford 在 2000 年代初推广。它的设计目标是:人类可读、机器易解析、语言无关。这三个目标至今仍然是 JSON 广泛取代 XML 成为 API 通信首选格式的核心原因。

但有一个常见的误解需要纠正:JSON 不是 JavaScript 对象的子集。JSON 比 JavaScript 对象字面量更严格。比如:

// ❌ 这在 JavaScript 中有效,但不是合法 JSON
{ name: "张三", age: 25, }

// ✅ 合法 JSON
{ "name": "张三", "age": 25 }

JSON 要求所有键必须用双引号包裹、不能有尾随逗号、不支持注释、字符串只能用双引号。这些约束让解析器可以更简单、更高效、更可预测地工作——代价是写起来比 JS 对象繁琐一些。

JSON 语法规则详解:最容易踩的 7 个坑

根据我们处理大量用户输入的经验,以下是开发者最常遇到的 JSON 语法错误:

  1. 键名未加双引号{name: "value"} 不合法,必须写成 {"name": "value"}。很多开发者习惯了 JavaScript 的对象简写,直接从代码里复制出来就以为可以当 JSON 用了。
  2. 尾随逗号{"a": 1, "b": 2,} —— 最后一个元素后面的逗号在 JavaScript 中允许,但 JSON 规范严格禁止。这个问题在手动编辑长 JSON 时特别常见。
  3. 单引号字符串{'name': 'value'} 在 JSON 中不合法。JSON 只接受双引号。如果你从 Python 代码复制字典,很容易踩这个坑。
  4. 注释混入:JSON 不支持 ///* */ 注释。很多配置文件(如 VS Code 的 settings.json)实际上使用的是 JSONC(JSON with Comments),而不是纯 JSON。
  5. 数字格式问题:前导零(007)、十六进制(0xFF)、NaN、Infinity 在 JSON 中都不合法。数字只能是十进制整数或浮点数。
  6. 未转义的控制字符:字符串中包含换行符、制表符等控制字符时需要用 \n\t 转义。直接把多行文本放进 JSON 字符串会失败。
  7. 重复键名:JSON 规范不禁止重复键,但大多数解析器会取最后一个值或者报错。如果 JSON 中有重复键,应该视为数据问题。
💡 实践建议: 不确定某个 JSON 片段是否合法?直接粘贴到我们的 JSON 格式化工具,它会即时告诉你错误位置和类型。比肉眼检查快 10 倍。

浏览器如何解析 JSON:JSON.parse 的内部机制

现代浏览器中的 JSON.parse() 并不是简单的 eval 包装。它经历了一个严格的解析流程:

  1. 词法分析(Tokenization):将字符串分解为 token 序列——左花括号、字符串字面量、冒号、数字、逗号等。如果遇到无法识别的字符(如未转义的控制字符),在这一步就会抛出 SyntaxError。
  2. 语法分析(Parsing):根据 JSON 文法规则构建抽象语法树。这一步检查结构是否正确——对象是否以 { } 正确闭合、数组元素之间是否有逗号分隔、键值对是否有冒号等。
  3. 值构建(Evaluation):将语法树转换为 JavaScript 对象。数字被转为 Number 类型,字符串被解码(处理 \uXXXX 等转义序列),布尔值和 null 被映射。

理解这个过程对调试很重要。当 JSON.parse() 报错时,错误消息通常会告诉你出错位置附近的字符。例如:

// 输入: '{"name": "张三", "age": 25,}'
// 错误: SyntaxError: Unexpected token } in JSON at position 29
// position 29 就是那个多余的逗号后面的位置

性能方面,现代浏览器对 JSON.parse 做了大量优化。V8 引擎(Chrome/Node.js)的 JSON 解析器是用 C++ 实现的,对于典型 API 响应(几 KB 到几百 KB),解析通常在微秒级完成。但如果 JSON 特别大(超过 10MB),解析可能成为性能瓶颈——这也是为什么大型数据集推荐使用流式解析或二进制格式。

生产中常见的 JSON 错误及定位方法

错误 1:API 返回的不是 JSON

开发中一个常见场景是:你调了一个 API,响应头写着 Content-Type: application/json,但实际返回的是 HTML 错误页面(如 502 Bad Gateway 的 Nginx 默认页)。JSON.parse() 会在第一个 < 字符处报错。

定位方法: 在解析之前先打印响应的前 200 个字符,或者用 response.text() 看一眼内容。

错误 2:BOM 头导致的解析失败

某些工具(特别是 Windows 上的旧版记事本)会在 UTF-8 文件开头添加 BOM(Byte Order Mark,\uFEFF)。这个不可见字符在 JSON 开头会导致解析失败,错误消息通常是 "Unexpected token"。

定位方法: 用 hexdump 查看文件前几个字节,或者用 response.text().then(t => console.log(t.charCodeAt(0))) 检查第一个字符编码。

错误 3:大整数精度丢失

JavaScript 的 Number 类型基于 IEEE 754 双精度浮点数,只能安全表示 -(2^53-1) 到 2^53-1 范围内的整数。超过这个范围的整数(如 Twitter 的 snowflake ID)在 JSON.parse 后会丢失精度:

JSON.parse('{"id": 12345678901234567890}')
// { id: 12345678901234567000 }  ← 精度丢失!

解决方案: 对于超过安全整数范围的值,应该在 JSON 中以字符串形式传输,或者在支持 BigInt 的环境中用自定义 reviver 处理。

格式化不是"变好看":缩进、排序和可读性的价值

很多开发者把 JSON 格式化理解成"把压缩的 JSON 变好看",但实际上格式化的价值远不止于此:

但是,JSON 格式化有一个被忽视的问题:键排序。很多格式化工具只是美化缩进,不改变键的顺序。当你对比两个逻辑上等价但键顺序不同的 JSON 时,diff 会显示大量无意义的差异。如果需要做精确的结构对比,建议先对键进行字母排序再格式化。

JSON 使用最佳实践与安全注意事项

  1. 永远不要用 eval() 解析 JSON: eval('(' + jsonStr + ')') 会执行 JSON 中的任意 JavaScript 代码,是严重的安全漏洞。始终使用 JSON.parse()
  2. 验证结构而非假设: 收到外部 JSON 后,不要假设某个字段一定存在或一定是某种类型。用 JSON Schema 或运行时类型检查来验证。
  3. 小心 JSON 注入: 如果你在拼接 JSON 字符串(比如手动构建),用户输入中的双引号和反斜杠需要正确转义。更好的做法是:先构建对象,再用 JSON.stringify 序列化。
  4. 敏感数据不要放 JSON 中明文传输: 即使是 HTTPS,JSON 内容在浏览器开发者工具中完全可见。不要在 JSON 中传输密码、令牌等敏感信息,除非经过加密。
  5. 控制 JSON 大小: 超过 1MB 的 JSON 响应应该考虑分页或流式传输。大 JSON 不仅消耗带宽,解析时的内存占用也值得关注。

在线 JSON 工具的正确使用姿势

在线工具的价值在于"随手可得",但要避免几个常见误区:

⚠️ 注意: 永远不要在生产环境或敏感数据上使用在线工具。不要把包含用户 PII(个人身份信息)、认证 Token、数据库连接字符串的 JSON 粘贴到任何在线页面中。先在本地脱敏(替换敏感字段为占位符),再使用在线工具格式化或校验。

在线 JSON 工具最适合这些场景:调试接口返回的测试数据、验证手写的配置 JSON、教学中演示 JSON 结构、快速格式化一个小的 JSON 片段。对于日常开发调试,这是一个非常高效的辅助手段——不需要切 IDE、不需要开 Postman、不需要写一行代码。

如果你在处理大量 JSON 或需要批量操作,建议使用命令行工具(如 jq)或 IDE 内置的 JSON 插件,它们提供了更强大的查询和转换能力。但在你需要"马上就看清楚这个 JSON 的结构"的时候,在线格式化工具就是最直接的解决方案。