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 支持且只支持六种数据类型:
"hello world"双引号括起的任意 Unicode 字符序列。支持反斜杠转义序列(\n、\t、\")。
42 / 3.14 / 1e10整数或浮点数。支持科学计数法(1e10)。JSON 层面不区分 int 和 float。
true / false字面量 true 或 false(仅小写)。没有 truthy/falsy 的概念——只有严格的布尔值。
null字面量 null(小写)。表示值的缺失。与 undefined 不同,后者不是 JSON 类型。
[1, "two", null]方括号中的有序值列表。元素可以是混合类型,数组可以任意嵌套。
{"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。
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 并非总是最佳选择,以下是与其他常见数据格式的对比:
语法更简单、文件更小、更易解析、更易读
不支持属性、处理指令或 XML 命名空间
需要文档元数据、混合内容模型或 XML Schema 时
语法更严格(歧义更少)、工具支持更好、可移植性更强
不支持注释,深度嵌套数据时略显冗长
人工编辑的配置文件、Docker Compose、GitHub Actions、Kubernetes 清单
更广泛的生态系统支持、解析更快、类型处理更可预测
没有原生日期类型,复杂嵌套结构时不够友好
Rust(Cargo.toml)、Python(pyproject.toml)、INI 风格的应用配置
支持结构化和嵌套数据,不局限于平面行列
文件体积大得多,纯表格数据时性能较差
电子表格数据、数据库导出、要在 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。
JSON 必须以 UTF-8、UTF-16 或 UTF-32 编码。JSON 文件开头的 BOM 不符合规范。
解析不受信任的 JSON 时,通过 __proto__ 键合并解析对象可能导致原型污染攻击。
{"key": null} 与缺失的 "key" 在语义上不同。null 表示字段存在但值为空;缺失表示字段未指定。
常见问题
JSON 是 JavaScript Object Notation 的缩写。尽管名称中包含 JavaScript,但 JSON 完全独立于语言。
不同。JSON 是一种文本格式,类似于 JavaScript 对象字面量,但规则更严格:键必须使用双引号,不支持 undefined、函数或注释。
不可以。JSON 规范不包含注释语法。如需注释,可考虑 JSONC、JSON5 或 YAML。
JSONP 是绕过浏览器同源策略的一种旧方法,已过时。请改用 CORS。
JavaScript:JSON.stringify(data, null, 2)。Python:json.dumps(data, indent=2)。终端:cat file.json | jq .
NDJSON 每行存储一个 JSON 对象,支持流式处理,常用于日志文件和大型数据导出。
标记之间的空白符无关紧要。格式化是风格问题,而非语义问题。
JSON 规范未设置大小限制。实际上受解析器内存和网络传输能力限制。
不能直接表示。二进制数据需先进行 Base64 编码再嵌入 JSON,这会使大小增加约 33%。
JSON5 是 JSON 的超集,增加了:无引号键、单引号字符串、尾随逗号、注释和多行字符串。