JSON、YAML 和 XML:到底什么时候该用哪一个
这三者都能表示同样的数据,但它们是为不同的用途而设计的,每一个在对方擅长的领域都显得相当笨拙。这里教你怎么选。
· 阅读需 1 分钟
三种能表示同样数据、却为不同用途而生的格式
JSON、YAML 和 XML 都能表示本质上相同的底层数据——嵌套的对象、列表、键值对、普通值——这正是为什么在三者之间做选择时,往往取决于习惯或框架的默认设置,而不是经过深思熟虑的决定。但这三者诞生于不同的时代,是为不同的主要用途设计的,这些原始设计目标至今仍体现为实实在在的实际差异:哪一种适合手动编辑,哪一种能被机器严格校验,哪一种在深层嵌套时依然可读,哪一种已经有一整套工具生态在默认支持它。基于这些差异而不是习惯来做选择,才能让格式选择真正做到明智,而不只是遵循惯例。
JSON:API 的默认选择,以及它赢得这个地位的原因
JSON 直接脱胎于 JavaScript 的对象字面量语法,这个出身正是它成为 Web API 数据交换默认格式的原因:任何 JavaScript 环境都能原生解析它,不需要任何库;它的语法足够简单,几乎任何其他语言都能在一个下午内正确实现;它严格的规则——不允许注释、不允许尾随逗号、键名必须用双引号——意味着 JSON 解析器几乎没有歧义需要处理,这让 JSON 既能快速解析,又容易正确生成。而这种严格性,也正是 JSON 作为人工手动编辑格式时的主要弱点:没有注释意味着无法在配置文件里留下解释性说明,标点符号密集的嵌套花括号语法一旦嵌套超过三四层,就变得很难用肉眼追踪。
这也是为什么 JSON 主导了机器对机器的通信——API 响应、服务之间的数据交换、任何主要由代码生成和消费而不是由人阅读和编辑的内容——而对于需要人手动维护的配置文件来说,它仍然显得有些笨拙。
YAML:专为人类阅读和编辑而设计
YAML 的设计优先级正好相反:以人类可读性和易于手动编辑为首要目标,代价是解析规范比 JSON 复杂得多。它用缩进而不是花括号来表示嵌套,用 `#` 支持真正的注释,并且在常见情况下允许不加引号的字符串,这一切都让格式良好的 YAML 文件读起来几乎像是普通的结构化笔记,而不是代码——这正是 YAML 成为大量开发工具默认配置文件格式的原因:CI/CD 流水线定义、容器编排清单、需要人直接阅读和修改的应用程序配置。代价是,YAML 依赖空白字符来表示结构,这让它在手动正确编辑时相当脆弱——一个缩进错位会悄悄改变某个代码块的归属,而不会抛出明显的错误——而且它更宽松、功能更丰富的规范,多年来在不同 YAML 解析库之间确实产生了记录在案的解析不一致问题,这种歧义是 JSON 严格得多的语法根本不会留出空间的。
XML:更冗长,但拥有 JSON 和 YAML 都无法完全比拟的校验能力和工具生态
XML 比 JSON 和 YAML 都更早出现,它的设计优先级又是另一回事:严格、可验证的文档结构,配合一整套成熟的周边标准——能在应用代码接触文档之前就验证其结构的模式语言、用于查询文档内部内容的 XPath、用于组合来自不同来源的词汇而不产生命名冲突的命名空间。在企业和以文档为中心的场景中,这种工具深度至今仍是 JSON 或 YAML 无法完全比拟的:那些对数据交换有严格要求、拥有标准化文档格式、以及围绕它构建了长期存在的遗留系统的行业,至今依然依赖 XML,这恰恰是因为这种校验和工具成熟度,而不是单纯的历史惯性。众所周知的代价是冗长——用 XML 表示同样的嵌套数据,通常比等价的 JSON 需要多出明显更多的字符,因为每个值都需要一对开始和结束标签,而不是一个标点符号——这也是随着 Web 服务日趋成熟、负载体积和解析简洁性变得比文档式校验更重要时,XML 在 API 默认格式的地位上被 JSON 取代的主要原因。
一种实用的选择方式
对于 API 请求或响应体,如今 JSON 几乎总是正确的默认选择——这是大多数客户端库、大多数文档工具、以及集成对接的另一端开发者会毫无摩擦地默认期待的格式。对于人需要经常阅读和手动编辑的配置文件——CI 流水线、应用配置、基础设施即代码的定义——YAML 的注释和更简洁的嵌套确实能派上真正的用场,前提是周边的工具能仔细校验语法,因为这正是 YAML 空白字符脆弱性最容易出问题的地方。对于以文档为中心、真正需要严格模式校验、跨组合词汇的命名空间、或者需要与现有的基于 XML 的企业系统集成的格式,XML 的冗长是为了换取两者都无法完全复制的工具成熟度,这是一个合理的代价。真正能让项目受益的格式选择,是与最经常读写这个文件的对象——无论是人还是机器——相匹配的那一个,而不是当下最时髦的默认选项。