YAML vs JSON vs TOML —— 该选哪个
「我应该用哪种序列化格式」的争论和配置文件的历史一样久。看了十五年各种团队选错之后,答案很少是「用最好的那个」——而是「用那个出错时你能闭着眼睛认出来的格式」。本文是我们实际使用的标准,外加一份一分钟就能套用的决策树。
三位选手,速览
JSON(RFC 8259)是「逃逸」出去的数据交换格式。语法严格、六种值、一种字符串定界符(双引号)、一种数字格式(十进制、无前导零)。每个主流语言的标准库里都自带解析器,跨实现的兼容性比谁都强。
YAML(1.2 规范)是吞下 DevOps 世界的配置格式。基于缩进的层级、标量默认按普通字符串处理、完整 Unicode 支持、锚点与别名实现交叉引用、三种风格写多行字符串。正常工作时很美;一旦哪里出问题,就是运维噩梦。
TOML(1.0 规范)是专为配置设计的新选手。键值结构、点分小节标题做命名空间、显式语法类型(字符串 vs 整数 vs 日期时间)、无空格敏感、无锚点。设计上既比 YAML 更适合人编辑,又比 YAML 更稳可解析——这两点它基本都做到了。
八条判断标准
- 谁在编辑。如果文件由非编程背景的人(运营、设计、市场)改,TOML 在可读性上赢——键和值是显式的、层级靠节标题而不是缩进,不会出现「这里到底是 null 还是 ~?」的问题。如果文件多半由工具写、少由人改,JSON 在工具链上赢——世界上每个编辑器都知道怎么高亮和校验 JSON。
- 谁在读。JSON 的读取器无处不在。YAML 的读取器主要在 Python、Ruby、Go、Rust、Java、Node.js、PHP——也就是把 YAML 选作默认配置格式的那批语言。TOML 在 Rust 生态(Cargo、Just、uv)里举足轻重,并正在扩散到 Python(pyproject.toml)、.NET、Go、Node.js(package.json 本质上就是 TOML 类格式,已经十年了)。
- 工具链成熟度。JSON 的工具链最成熟(jq、JSON Schema、jsonschema、JSON Patch、JSON Canonicalization Scheme)。YAML 有像样的解析器,但验证工具几乎没有——大多数 YAML 部署最后都把文件解析成内部 AST,再用应用代码校验结构,这种做法很脆弱。TOML 正在崛起,仍比 JSON 年轻。
- 严格度。JSON 严格。YAML 松到危险的程度:
NO、yes、on、off在 YAML 1.1 里都是布尔(1.2 已弃用,但很多解析器出于兼容仍支持);flow style 允许尾逗号;2024-01-15会被解析为日期;1.0和1在不同版本里被解析成相同或不同。TOML 通过语法显式区分类型——不靠猜测。 - 体积。JSON 最紧凑(key 不加引号、无意义空白)。YAML 最松散,因为有缩进。TOML 在中间,显式引号多几个字节但消除歧义。
- 注释。JSON 禁止。YAML 和 TOML 都允许;TOML 的 # 风格对程序员更友好,YAML 的 # 风格等价但在长值里视觉更噪。
- 往返语义。这是很多真实系统的杀手标准。JSON 保留插入顺序(RFC 8259 §4)。YAML 保留顺序但允许重复 key,下游消费方都不喜欢。TOML 没有正式规定 map 的 key 顺序;多数解析器保留插入顺序;一些使用排序顺序。
- 嵌入到源码里。TOML 有最干净的「第一行声明元数据、剩下都是配置」人体工学——Cargo.toml、pyproject.toml、Justfile 都用得很好。YAML 嵌入到 shell 脚本里(Kubernetes 清单)也凑合,前提是你用
|literal 块标量;不这样做的话,shell 会把缩进剥掉从而毁掉你的 YAML。
决策树
如果你从零开始,且以上标准没有给出明显答案,这段简短 rubric 能解决 90% 的情形:
- 应用对应用数据交换的默认:JSON。先做线上格式,如果要让人读再转换。
- 人编辑的配置文件的默认:TOML。特别是文件在版本控制里、要走 code review 的。
- YAML 仍然适用的场景:文件属于 Kubernetes / GitHub Actions / Ansible 生态——这些场景里 YAML 是通用语;文件确实需要交叉引用(锚点与别名);文件被一个已经说 YAML 的工具消费,硬扩展很难。
- 避免 YAML 的场景:新 API;新的工具配置(TOML 表达能力同样够用);任何对往返确定性有要求的;任何会交付给几十个团队独立调试的。
往返是一个终究会踩到的坑
工具产出一个 YAML 文件,人改一遍,同一个工具再解析一次——理想情况下字节级一致。实际几乎没有任何 YAML 实现做对——注释漂移、key 顺序变化、标量风格在 quoted 和 unquoted 之间切换,你的 diff 里全是并非真实变更的噪音。YAML ↔ JSON 转换器 通常就是逃生口:往返一次到 JSON、拿规范化形式、再决定哪一边是 source of truth。
就签名 / 哈希 / 规范化而言,三者都没有原生规范化形式(RFC 8785 是 JSON 专属)。JSON 的规范化故事最强;YAML 没有规范化规范;TOML 也没有。如果你需要对配置签名,先转 JSON、规范化到 JCS、对规范化字节签名——这是唯一的跨工具可重现路径。
收尾
没有万能赢家。最可靠的启发式是「用那个凌晨两点挂掉时你能看懂报错格式的格式」。对 2026 年大多数团队,人编辑的配置用 TOML、跨进程边界的所有东西用 JSON。YAML 在部署目标是 YAML 原生(Kubernetes 清单、GitHub Actions、Ansible playbook、GitLab CI)时仍然是对的——但把每个 YAML 文件当成一个自带方言的小型 DSL,并准备好为之辩护。