JSON 最佳实践:格式化、验证与 API 设计
JSON 是现代 Web 的通用语言。本指南涵盖格式化约定、Schema 验证、RESTful API 设计模式, 以及 JSON 与 XML、YAML 的对比——所有内容均基于官方 RFC 8259 规范。
什么是 JSON?
JSON(JavaScript 对象表示法)定义于 RFC 8259,是一种轻量级、基于文本、 与语言无关的数据交换格式。它派生自 JavaScript 对象字面量语法,但并非 JavaScript 的严格子集。 JSON 使用两种通用结构——名称/值对(对象)和有序列表(数组)——来表示结构化数据, 这两种结构几乎直接映射到所有现代编程语言的数据结构。
JSON 最初由 Douglas Crockford 提出,后由 IETF 在 RFC 8259中标准化。该格式刻意保持极简:没有注释、没有尾随逗号、没有单引号字符串,只有一个称为 "number" 的数字类型。 正是这种极简性使 JSON 既易于解析,又便于人类阅读。
如今,JSON 已成为 RESTful API、NoSQL 文档存储(如 MongoDB 和 CouchDB)、配置文件(package.json、tsconfig.json) 以及结构化日志的事实标准。理解其规则对于任何在 Web 上工作的开发者都至关重要。
JSON 结构和数据类型
RFC 8259 准确定义了六种数据类型。每个 JSON 值都属于以下之一:string(字符串)、number(数字)、boolean(布尔)、null(空值)、object(对象) 或 array(数组)。没有日期、没有二进制、没有整数与浮点之分,也没有 undefined。 了解这一约束是编写正确 JSON 的第一步。
- ✓String:双引号包裹的 Unicode 文本。支持
\n、\t、\uXXXX等转义序列。单引号无效。 - ✓Number:单一的 IEEE 754 双精度风格值。没有单独的整数类型——在 JavaScript 运行时中,超过 253-1 的大整数可能丢失精度。
- ✓Boolean:字面量
true和false。加引号的版本是字符串,不是布尔值。 - ✓Null:字面量
null表示值的缺失。它不等于空字符串、零或undefined。 - ✓Object:名称/值对的无序集合,用大括号
{ }包裹。键必须是字符串。 - ✓Array:值的有序列表,用方括号
[ ]包裹。值可以是混合类型。
格式化约定(让 JSON 更易维护):使用 2 空格缩进、键名采用 camelCase、 永远不要尾随逗号,并优先使用 null而非空字符串来表达 "无值"。
Schema 验证
JSON Schema 提供了一种标准化的方式来注释和验证 JSON 文档。 它由 JSON Schema 规范定义,允许你描述 JSON 对象的预期结构、数据类型、必填字段、取值范围和约束。 Schema 验证对 API 至关重要,因为它能在边界处捕获格式错误的输入,防止下游运行时错误, 并为数据的生产者和消费者提供活的文档。
Schema 文档本身也是 JSON。当前草案版本为 2020-12。最值得掌握的关键字有:
- ✓
type:将值限制为六种 JSON 类型之一。 - ✓
required:必须存在的属性名数组。 - ✓
properties:为对象的每个键定义 schema。 - ✓
items:为数组元素定义 schema。 - ✓
format:为字符串附加语义注释,如date-time、email或uri。 - ✓
additionalProperties: false:禁止未知键——有助于发现 API 客户端中的拼写错误。
最佳实践:在服务端(保护数据存储)和客户端(给用户快速反馈)都进行验证。 标准实现库如 ajv(JavaScript)、jsonschema(Python)和gojsonschema(Go)可在毫秒级完成校验。
API 设计最佳实践
使用 JSON 的 RESTful API 设计需要一致的约定——涵盖资源命名、状态码、 错误封装和分页。设计良好的 JSON API 把响应体视为契约:每个字段都有稳定的类型, 每个错误都有机器可读的代码,每个集合都支持分页,让客户端可以无意外地理解数据。
能跨团队、跨语言扩展的约定:
- ✓路径用名词而非动词:
/users/42而非/getUser?id=42。HTTP 方法表达动词。 - ✓命名风格保持一致:为整个 API 选择
camelCase或snake_case,永远不要在同一响应中混用。 - ✓用稳定信封封装错误:始终返回
{ "error": { "code": "...", "message": "..." } },并附带合理的 HTTP 状态码(4xx 客户端错误,5xx 服务端错误)。 - ✓每个列表端点都分页:使用
cursor或offset/limit,并返回next_cursor让客户端能获取下一页。 - ✓日期用 ISO 8601 字符串:
"2026-07-29T10:30:00Z"跨时区无歧义。永远不要用 epoch 数字作为 JSON 数字——超过 253-1 后会超出安全整数精度。 - ✓为 API 版本化:路径前缀
/v1/,这样破坏性变更可以以/v2/发布而不影响现有客户端。
一个常见错误是:同一资源在不同上下文中返回不同的形状。如果 /users/42返回 User 对象,那么其他包含用户的端点都应嵌入相同的 User 形状。可预测的形状让客户端 SDK 的编写变得轻而易举。
JSON vs XML 对比
与 XML 相比,JSON 具有更小的负载、更快的解析速度,且数据模型直接映射到大多数编程语言。 XML 擅长处理带混合内容、属性、命名空间和样式表(XSLT)的文档型数据。对于通过 HTTP 进行纯数据交换 ——现代 API 的主流场景——JSON 是正确的默认选择,也正是 RFC 8259 设计的初衷。
XML 需要解析器理解开始标签、结束标签、属性、CDATA 段和命名空间。JSON 只需要两种结构标记 (大括号和方括号)加上六种值类型。结果是:典型的 JSON 负载比等效 XML 小 20–40%,解析时间也只是其一小部分。
不过,XML 在需要模式验证文档(XSD)、样式(XSLT)或带嵌入标记的散文等混合内容的领域仍然占优。 SOAP 服务、Office Open XML(.docx)和 SVG 都是 XML,这是有充分理由的。请选择适合工作的工具。
对比表:JSON vs XML vs YAML
| 方面 | JSON | XML | YAML |
|---|---|---|---|
| 语法风格 | 键值对和数组 | 带属性和嵌套元素的标签 | 基于缩进的结构 |
| 文件大小 | 紧凑(无标签) | 最大(标签冗长) | 最小(无大括号或引号) |
| 解析速度 | 快(多数语言原生支持) | 较慢(DOM/SAX 解析) | 较慢(缩进解析) |
| 注释 | RFC 8259 不允许 | 支持(<!-- -->) | 支持(# 风格) |
| 数据类型 | 6 种:string、number、boolean、null、object、array | 所有数据都是文本,类型推断 | 丰富:包括日期、null、锚点 |
| 最佳用途 | API、Web 数据交换、配置 | 文档、SOAP、企业级模式 | 配置文件、CI/CD 流水线 |
| 标准 | RFC 8259 | W3C XML 1.0 | YAML 1.2 |
| 人类可读性 | 良好(但无注释) | 良好(但冗长) | 极佳(最简洁) |
技术参考:RFC 8259
RFC 8259:JavaScript 对象表示法(JSON)数据交换格式是 JSON 的权威规范。它废弃了 RFC 7159 和 RFC 4627。每个开发者都应了解的关键点:
- ✓编码:JSON 文本默认应以 UTF-8 编码。早期 RFC 允许 UTF-16 和 UTF-32;RFC 8259 为互操作性强制要求 UTF-8。
- ✓无注释:JSON 不允许注释。允许注释的配置工具(JSON5、JSON-C)使用的是非标准扩展。
- ✓键名唯一:对象的键名 SHOULD 唯一。当存在重复时,解析器会接收所有值,但只有最后一个值可访问——行为由实现定义。
- ✓数字精度:数字在语法上无限制,但以 IEEE 754 双精度存储的实现无法精确表示超过 253-1 的整数。
- ✓顶层值:JSON 文本是单个序列化的值——可以是对象或数组,也可以是裸字符串、数字、布尔值或 null。
对于验证词汇表,配套标准是 JSON Schema 规范, 当前草案为 2020-12。RFC 8259 与 JSON Schema 共同构成了每个现代 JSON API 的基础。
常见问题
什么是 JSON?它有什么用途?
JSON(JavaScript 对象表示法)是一种轻量级、基于文本的数据交换格式,由 RFC 8259 定义。它使用人类可读的键值对和数组来表示结构化数据。JSON 与语言无关,是 Web 服务器与客户端之间数据交换、配置文件和 NoSQL 数据库的事实标准。
什么是 JSON Schema?它为什么重要?
JSON Schema 是一种词汇表,用于注释和验证 JSON 文档。它定义了 JSON 对象的预期结构、数据类型、必填字段、取值范围和约束。Schema 验证对 API 至关重要,因为它能在边界处捕获格式错误的输入,防止运行时错误,并为数据的生产者和消费者提供活的文档。
JSON API 响应应该用 camelCase 还是 snake_case?
两者都有效,但关键是保持一致。大多数 JavaScript 生态倾向于 camelCase,因为它符合原生 JS 约定;而 Python 后端通常默认使用 snake_case。最佳实践是为每个 API 选择一种风格,明确文档化,且永远不要在同一个响应中混合使用。许多团队在传输层使用 camelCase,在框架边界处进行转换。
JSON 和 XML 有什么区别?
JSON 是一种轻量级的、基于键值对的格式,专为数据交换而设计;而 XML 是一种标记语言,支持属性、命名空间和混合内容。JSON 在传输上更小、解析更快,并直接映射到大多数编程语言的数据结构。XML 更重,但更适合需要验证(XSD)或样式(XSLT)的文档型数据。对于大多数现代 API,JSON 是首选格式。