JSON 和 YAML 解决的是同一个问题 —— 把结构化数据表示成文本 —— 但它们的取舍正好相反。JSON 为机器无歧义解析而优化;YAML 为人类编写而优化。从 YAML 1.2 开始,每一份合法的 JSON 文档也是合法的 YAML。本指南比较它们的语法、类型和特性,并说明何时该选哪个。
简短答案
程序之间交换的数据用 JSON —— API 响应、消息 payload、任何机器生成的东西。要人手写、手编辑的文件用 YAML —— CI pipeline、Kubernetes manifest、应用配置 —— 这些地方注释和可读性很重要。
并排语法对比
同样的数据,两种格式各写一遍:
# YAML
service: api
replicas: 3
ports:
- 8080
- 8443
env:
LOG_LEVEL: info
DEBUG: false// JSON
{
"service": "api",
"replicas": 3,
"ports": [8080, 8443],
"env": {
"LOG_LEVEL": "info",
"DEBUG": false
}
}YAML 用缩进代替花括号和方括号,省掉了大多数引号,并允许注释。JSON 更啰嗦,但没有有意义的空白,这让它远比 YAML 更容易可靠地解析和生成。
YAML 是 JSON 的超集
从 YAML 1.2(2009)开始,YAML 是 JSON 的严格超集 —— 任何合法 JSON 文档都是 合法 YAML,因为 YAML 直接采用了 JSON 的「flow」语法。所以你把 JSON 粘进 YAML 文件就能直接跑。背后的历史见 YAML 1.2 与 JSON 兼容性。
# 这是合法 YAML —— 同时也是合法 JSON
{"service": "api", "replicas": 3}特性比较
| 特性 | JSON | YAML |
|---|---|---|
| 注释 | 无 | 有(#) |
| 尾随逗号 | 不允许 | 不适用(block 风格里没有逗号) |
| 多行字符串 | 只能用转义的 \n | 原生支持(| 与 >) |
| Anchor / 引用 | 无 | 有(& / *) |
| 一个文件多个文档 | 不支持 | 支持(用 --- 分隔) |
| 有意义的空白 | 无 | 有(缩进有意义) |
| 解析复杂度 | 极简 | 复杂 |
| 适合场景 | 机器间数据交换 | 人手编辑的配置 |
类型处理:YAML 的尖刺
YAML 急着推断类型,所以会出现 JSON 强制加引号能避开的意外:
# 「Norway problem」—— 在 YAML 1.1 解析器里这些会变布尔
countries:
- NO # → false (!)
- SE
- true # → 布尔,不是字符串 "true"
version: 1.20 # → 数字 1.2,末尾的零丢了
zip: 01234 # → 668(在某些解析器里被当成八进制) JSON 完全没有这些歧义:"NO" 永远是字符串 NO,"01234" 永远就是那个字符串。当一个 YAML 值必须是字符串时,请明确加引号。
TOML 和 JSON5 处在什么位置
另外两种常见的「对人友好」配置格式经常在同一个话题里出现:
- TOML —— section/key 风格,专为人手编辑的应用配置设计(Cargo、Poetry、Hugo)。比 YAML 更严格,没有有意义的缩进,原生类型化的值(datetime、整数、浮点、数组、内联表)。当数据主要是扁平的表时最合适。
- JSON5 —— 给开发者用的宽松 JSON:支持注释、尾随逗号、不带引号的 key、单引号、多行字符串。不是 标准 JSON 解析器能直接接受的;你要用 JSON5 库才行(或者用一个 JSONC 解析器,处理「注释 + 尾随逗号」子集,比如
tsconfig.json)。
大致的定位:机器间交换用 JSON;深度嵌套、人手编辑的配置用 YAML;扁平的应用 / 工具配置用 TOML;当你想要「带注释的 JSON」做编辑器配置又不想接受 YAML 的空白规则时,用 JSON5/JSONC。
什么时候用哪个
- 用 JSON:REST/GraphQL API、消息队列、浏览器
localStorage、package.json、任何由代码生成或消费的东西。 - 用 YAML:GitHub Actions / GitLab CI、Kubernetes 和 Docker Compose、Ansible playbook、需要人手编辑并写注释的应用配置。
一个常见模式:为可读性用 YAML 编写配置,然后在构建或加载时转成 JSON,让应用本身只解析 JSON。
在 JSON 和 YAML 之间转换
# Python —— YAML 转 JSON
import yaml, json
data = yaml.safe_load(open('config.yaml'))
print(json.dumps(data, indent=2))
# 用 yq 在命令行
yq -o=json '.' config.yaml # YAML → JSON
yq -P '.' config.json # JSON → YAML或者用 fixjson 的 YAML ⇄ JSON 转换器 在浏览器里立刻转换 —— 贴 YAML 得到 JSON(或反过来),数 据不会发到任何服务器。
常见问题
YAML 比 JSON 好吗?
没有哪个「更好」—— 它们是给不同活儿调过的。人手编辑的配置 YAML 更好(注释、可读性);机器间数据交换 JSON 更好(简单、快、解析无歧义)。
JSON 是合法 YAML 吗?
是。从 YAML 1.2 开始,YAML 是 JSON 的严格超集,所以任何合法 JSON 文档都是合法 YAML。反过来不成立 —— 大多数 YAML 不是合法 JSON。
为什么 YAML 把「NO」变成 false?
YAML 会从没引号的 scalar 推断类型,有些解析器会把 NO、yes、on、off 读成布尔(「Norway problem」)。给这个值加引号("NO")就能强制它是字符串。JSON 用强制引号完全避开了这个问题。
配置文件该用 YAML 还是 JSON?
需要人手编辑、需要注释和多行字符串就用 YAML;由工具生成或消费就用 JSON。很多团队用 YAML 编写,加载时转 JSON。
在浏览器里转换和校验
- YAML ⇄ JSON 转换器 —— 任意方向转换,全部在浏览器端
- YAML 格式化工具 —— 格式化、重缩进、校验 YAML
- 什么是 JSON? —— YAML 是它的超集的那个格式
- 如何格式化 JSON —— 把转换出来的结果格式化
- YAML 1.2 与 JSON 兼容性 —— YAML 是怎么变成 JSON 超集的