← 返回博客首页

JSON 完全指南:结构、安全陷阱与现代用法

什么是 JSON?

JSON(JavaScript Object Notation,RFC 8259)是一种轻量级的、与语言无关的数据交换格式。它用极简的文本描述结构化数据,既能让人直接读懂,又能被几乎所有编程语言以极低成本解析。今天你打开的每一个 App、调用的每一个 REST API、写入的每一个 NoSQL 文档,背后几乎都在用 JSON 传递数据。

JSON 之所以能击败 XML 成为 Web 时代的事实标准,核心原因只有三个:够简单(六种类型覆盖绝大多数场景)、够严格(没有歧义,解析结果可预测)、够通用(从浏览器到嵌入式设备都有原生支持)。

JSON 的六种数据类型

理解 JSON 的第一步,是记住它只有六种值类型,不会有第七种:

类型 示例 说明
字符串 "oltool" 必须用双引号包裹,支持 \n\t\uXXXX 等转义
数字 423.14-0.5 不区分整数与浮点,统一按双精度处理
布尔 true / false 小写,不是字符串
空值 null 表示"有值但为空",区别于"字段不存在"
对象 {"k": "v"} 无序的键值对,键必须是字符串
数组 [1, 2, 3] 有序的值列表,元素可以是任意类型

一个真实世界里的 JSON 往往同时包含这些类型:

{
  "user": {
    "id": "u_1001",
    "name": "彬哥",
    "active": true,
    "roles": ["admin", "editor"],
    "metadata": null
  },
  "score": 98.5
}

嵌套结构:对象与数组的组合

JSON 的强大之处在于对象可以嵌套对象、数组可以嵌套数组、对象和数组还能互相嵌套。这种组合足以表达任意复杂度的业务数据,而语法始终保持一致:

  • 对象表达"一条记录的属性"。
  • 数组表达"一组同构的元素"。
  • 对象数组表达"一张表"(最常见的 API 返回形态)。

当层级过深时,人的肉眼很难看清结构。开发时建议先用 JSON 格式化 工具把压缩的一行展开成带缩进的树,或用 JSON 树形查看器 折叠浏览;需要把后端返回的大文档转成表格分析时,可以用 JSON 转 CSV

典型用法:API、配置与存储

1. 接口数据交换。 这是 JSON 的主战场。请求体、响应体、Webhook 回调几乎都是 JSON。它的严格类型让前后端"说什么就是什么",不需要像 XML 那样先约定 schema 才能解析。

2. 配置文件。package.jsontsconfig.json,Node 生态把 JSON 当成默认的声明格式。需要人工频繁编辑的配置则更常写成 YAML,再在构建期转成 JSON 给程序消费——可借助 YAML 转 JSONJSON 转 YAML 互转。

3. 文档型存储。 MongoDB、DynamoDB、RedisJSON 等直接用 JSON 文档建模数据,字段可以随记录灵活增减,特别适合 schema 演进快的场景。

与 XML / YAML / MessagePack 的取舍

维度 JSON XML YAML MessagePack
可读性 一般 最好 差(二进制)
解析速度 最快
注释支持
体积 最小
典型场景 API / 存储 遗留系统 / SOAP 人工配置 高性能二进制传输

结论很直接:机器之间高频交换选 JSON,人工写的配置选 YAML,极限性能/带宽场景选 MessagePack(底层仍是 JSON 的语义)。XML 如今主要在银行、电信等遗留系统里出现,新项目很少主动选择。

高频踩坑点(务必注意)

1. 大数精度丢失

这是最隐蔽、最致命的坑。JSON 没有整数类型,所有数字都按 IEEE 754 双精度浮点解析。超过 2^53(约 9007 万亿)的整数无法被精确表示——典型受害者是 64 位雪花 ID、数据库自增主键、身份证号。一旦在 JavaScript 里 JSON.parse,大整数会被悄悄四舍五入成近似值,且不会报错。

防御:跨语言传输大整数时优先用字符串;前端需要用 JSON.parsereviver 配合 BigInt,或使用支持大数的解析库。

2. 末尾逗号与引号

JSON 比 JavaScript 严格:对象/数组最后一个元素后面不能有逗号,键必须用双引号(单引号非法),字符串内部的双引号必须转义为 \"。这些在浏览器控制台里能跑的写法,到了标准 JSON 解析器里全部报错。

3. 字符串里的换行与不可见字符

从 Excel、 Word 或网页文本框复制进 JSON 的多行文本,常常夹带真实的换行符、制表符或 BOM。标准 JSON 要求字符串里的换行必须写成 \n,原始换行会直接让解析失败。提交前用格式化工具做一次清洗和校验能省掉大量调试时间。

4. 循环引用与函数

JSON.stringify 遇到循环引用的对象会直接抛 TypeError;它也会自动丢弃函数、undefined 和 Symbol。如果你的数据里混入了这些类型,序列化结果会和预期悄悄不一致——尤其是把前端状态整体转 JSON 时极易中招。

5. JSON 注入

把不可信的用户输入直接拼进 JSON 字符串(而不是用 JSON.stringify),或在前端用 eval / JSON.parse 解析来路不明的字符串,都可能引发注入。始终用标准序列化/解析 API,并对外部输入做校验。

现代工作流建议

所有这些操作都能在码屋(Mawu)的在线工具里本地完成——数据只存在于你的浏览器,不上传任何服务器,断网也能用。

小结

JSON 看似简单,却是现代软件最重要的"通用语"。掌握它的六种类型与嵌套规则只是起点,真正拉开差距的是对精度陷阱、严格语法、注入风险的警惕。把它当成一个需要被尊重和校验的契约,而不是随手拼的字符串,你的接口和配置会少掉一大类诡异 bug。

常见问题

JSON 和 JavaScript 对象有什么区别?

JSON 是一种纯文本数据格式,语法上借鉴了 JavaScript 对象字面量,但它是语言无关的字符串,键必须用双引号,不允许注释、函数、undefined 和末尾逗号;JavaScript 对象是内存中的数据结构,键可不加引号,支持函数和更多类型。

为什么大整数在 JSON 里会丢精度?

JSON 没有独立的整数类型,所有数字都按 IEEE 754 双精度浮点数解析。大于 2^53 的整数(如 64 位雪花 ID、数据库主键)无法被精确表示,解析后会四舍五入。跨语言传输大整数时应优先用字符串,或在支持 BigInt 的解析器中显式处理。

JSON 能不能写注释?

标准 JSON(RFC 8259)不允许注释。需要注解时常见做法是:改用 JSONC(如 VS Code 配置、tsconfig)、用单独的字段记录元信息,或改用 YAML/TOML 这类允许注释的格式。切勿依赖非标准解析器偷偷支持注释,否则会破坏跨系统互操作性。

JSON 解析失败一般怎么排查?

绝大多数解析错误来自:末尾多余逗号、单引号而非双引号、键未加引号、字符串里的换行或制表符未转义、以及 BOM 或不可见字符。先用格式化/校验工具定位错误行列号,再逐项修正。生产环境应捕获解析异常并记录原始报文,便于复现。

JSON 和 YAML 该选哪个?

JSON 更适合机器之间高频交换(解析快、类型严格、生态广泛);YAML 更适合人工编写的配置(可读性好、支持注释、缩进表达层级)。两者可相互转换:配置写 YAML、运行时转 JSON 给程序消费,是 DevOps 里的常见组合。

← 返回博客首页