JSON

13 tools

什么是 JSON?

JSON(JavaScript Object Notation)是一种轻量级的基于文本的数据交换格式,易于人类阅读和编写,也便于机器解析和生成。尽管起源于 JavaScript,JSON 与语言无关,现已成为 Web 数据交换的事实标准。

JSON 以键值对的形式表示数据,组织成对象和数组。其简洁性使其成为 REST API、配置文件和数据存储的主导格式。

简短历史

JSON 由 Douglas Crockford 在 2000 年代初正式确立。规范于 2001 年发布在 json.org 上,RFC 4627 于 2006 年发布,当前 ECMA-404 标准于 2013 年发布。

在 JSON 之前,XML 是 Web 上的主流数据交换格式。JSON 的极简主义——无属性、无处理指令、无命名空间——使其立即广受欢迎。到 2010 年,JSON 已在很大程度上取代了 Web API 中的 XML。

JSON 数据类型

JSON 支持且只支持六种数据类型:

String"hello world"

双引号括起的任意 Unicode 字符序列。支持反斜杠转义序列(\n、\t、\")。

Number42 / 3.14 / 1e10

整数或浮点数。支持科学计数法(1e10)。JSON 层面不区分 int 和 float。

Booleantrue / false

字面量 true 或 false(仅小写)。没有 truthy/falsy 的概念——只有严格的布尔值。

Nullnull

字面量 null(小写)。表示值的缺失。与 undefined 不同,后者不是 JSON 类型。

Array[1, "two", null]

方括号中的有序值列表。元素可以是混合类型,数组可以任意嵌套。

Object{"key": "value"}

花括号中的无序键值对集合。键必须是字符串,值可以是任意 JSON 类型。

{
  "string":  "hello world",
  "number":  42,
  "float":   3.14,
  "boolean": true,
  "null":    null,
  "array":   [1, 2, 3],
  "object":  { "nested": "value" }
}

JSON 语法规则

JSON 有严格的语法规则,细小的偏差会导致解析错误:

仅使用双引号字符串

所有字符串值和对象键必须使用双引号。单引号不是有效的 JSON。

不允许尾随逗号

JSON 不允许在数组最后一个元素或对象最后一个属性之后使用尾随逗号。

不允许注释

JSON 没有注释语法。// 和 /* */ 均无效。如需注释,考虑使用 JSON5 或 YAML。

不支持 undefined 或函数

JSON 仅支持六种原始类型。undefined、NaN、Infinity 和函数等 JavaScript 值无法表示。

对象键必须是字符串

所有对象键必须是带引号的字符串。数字键或裸标识符均不允许。

区分大小写

JSON 区分大小写。true、false 和 null 必须全部小写。

无效 JSON 与有效 JSON

无效
{
  'name': 'Alice',       // single quotes — invalid
  age: 30,              // unquoted key — invalid
  "scores": [1, 2, 3,], // trailing comma — invalid
  "note": undefined     // undefined — invalid
}
有效
{
  "name": "Alice",
  "age": 30,
  "scores": [1, 2, 3],
  "note": null
}

现代 Web 中的 JSON

REST API

JSON 是 REST API 请求和响应的标准正文格式。几乎所有编程语言都内置了 JSON 解析器。

配置文件

package.json、tsconfig.json、.eslintrc 等众多开发者工具使用 JSON 进行配置。

NoSQL 数据库

MongoDB、CouchDB、Amazon DynamoDB 等文档数据库以 JSON 文档格式存储数据。

前端状态与数据

localStorage 和 sessionStorage 存储字符串,因此 JSON.stringify/JSON.parse 被频繁用于序列化 JavaScript 对象。

JSON 与其他格式比较

JSON 并非总是最佳选择,以下是与其他常见数据格式的对比:

JSON vs XML
JSON 相对于 XML 的优势

语法更简单、文件更小、更易解析、更易读

JSON 相对于 XML 的劣势

不支持属性、处理指令或 XML 命名空间

何时选择 XML

需要文档元数据、混合内容模型或 XML Schema 时

JSON vs YAML
JSON 相对于 YAML 的优势

语法更严格(歧义更少)、工具支持更好、可移植性更强

JSON 相对于 YAML 的劣势

不支持注释,深度嵌套数据时略显冗长

何时选择 YAML

人工编辑的配置文件、Docker Compose、GitHub Actions、Kubernetes 清单

JSON vs TOML
JSON 相对于 TOML 的优势

更广泛的生态系统支持、解析更快、类型处理更可预测

JSON 相对于 TOML 的劣势

没有原生日期类型,复杂嵌套结构时不够友好

何时选择 TOML

Rust(Cargo.toml)、Python(pyproject.toml)、INI 风格的应用配置

JSON vs CSV
JSON 相对于 CSV 的优势

支持结构化和嵌套数据,不局限于平面行列

JSON 相对于 CSV 的劣势

文件体积大得多,纯表格数据时性能较差

何时选择 CSV

电子表格数据、数据库导出、要在 Excel 或 pandas 中打开的数据

JSON Schema

JSON Schema 是一种用于验证 JSON 文档结构的词汇表,描述 JSON 值的预期类型、必需字段和约束条件。当前版本为 JSON Schema 2020-12。

ajv(JavaScript)、jsonschema(Python)等工具以及众多 IDE 的内置验证器都支持 JSON Schema。OpenAPI 使用 JSON Schema 描述 API 请求和响应正文。

常见 JSON 陷阱

数字精度损失

JSON 数字解析为 IEEE 754 双精度浮点数。大于 2^53 的整数会损失精度。请将大型 ID 作为字符串传递。

没有日期类型

JSON 没有日期类型。日期通常序列化为 ISO 8601 字符串或 Unix 时间戳。

循环引用会导致序列化崩溃

JSON.stringify 对循环对象引用会抛出 TypeError。

Unicode 和 BOM 问题

JSON 必须以 UTF-8、UTF-16 或 UTF-32 编码。JSON 文件开头的 BOM 不符合规范。

原型污染

解析不受信任的 JSON 时,通过 __proto__ 键合并解析对象可能导致原型污染攻击。

null 与缺失键

{"key": null} 与缺失的 "key" 在语义上不同。null 表示字段存在但值为空;缺失表示字段未指定。

常见问题

JSON 是什么的缩写?

JSON 是 JavaScript Object Notation 的缩写。尽管名称中包含 JavaScript,但 JSON 完全独立于语言。

JSON 和 JavaScript 对象相同吗?

不同。JSON 是一种文本格式,类似于 JavaScript 对象字面量,但规则更严格:键必须使用双引号,不支持 undefined、函数或注释。

JSON 可以有注释吗?

不可以。JSON 规范不包含注释语法。如需注释,可考虑 JSONC、JSON5 或 YAML。

JSON 和 JSONP 有什么区别?

JSONP 是绕过浏览器同源策略的一种旧方法,已过时。请改用 CORS。

如何将 JSON 格式化为可读形式?

JavaScript:JSON.stringify(data, null, 2)。Python:json.dumps(data, indent=2)。终端:cat file.json | jq .

什么是 NDJSON 或 JSON Lines?

NDJSON 每行存储一个 JSON 对象,支持流式处理,常用于日志文件和大型数据导出。

JSON 中空白符重要吗?

标记之间的空白符无关紧要。格式化是风格问题,而非语义问题。

JSON 文件的最大大小是多少?

JSON 规范未设置大小限制。实际上受解析器内存和网络传输能力限制。

JSON 能表示二进制数据吗?

不能直接表示。二进制数据需先进行 Base64 编码再嵌入 JSON,这会使大小增加约 33%。

什么是 JSON5?

JSON5 是 JSON 的超集,增加了:无引号键、单引号字符串、尾随逗号、注释和多行字符串。