JSON、YAML 还是 TOML:配置文件格式的诚实对比
iLoveConverter Team 5 分钟读完
每个开发者都对配置格式积累了看法,通常是拿 YAML 缩进的伤换来的。三种主流格式并存有真实原因,而在它们之间转换是日常工作——CI 管线要 YAML,应用配置要 TOML,API 要 JSON。下面是诚实的对比,以及按下转换键之前值得知道的那些坑。
一句话版本
- JSON(2001)——通用数据交换格式。机器优先,啰嗦,零注释。
- YAML(2001)——人类可读的重型选手。缩进驱动,功能丰富,偶尔危险。
- TOML(2013)——「有尊严的配置文件」格式。显式、无歧义,为人手维护的文件而生。
JSON:交换的骨架
JSON 赢在无聊:一页纸的规范、每种语言都有解析器、结构直接映射编程数据类型。API、包仓库、浏览器工具——凡是机器对机器说话的地方都是它。
它的局限是人的局限。没有注释(永恒的抱怨——从 "//" 键到废弃配置项,每个 workaround 都是一道疤),强制引号和大括号,多行字符串丑得飞快。JSON 为程序书写优化,被迫手改 200 行 package-lock.json 时你立刻能体会到。
一个值得敬畏的细节:JSON 的数字模型。超过 2^53 的大整数在 JavaScript 工具链里丢精度(外部系统的 ID 被悄悄损坏);重复键在规范里属于未定义行为——多数解析器保留最后一个,转换时数据可能被悄悄吞掉。
YAML:强大,偶尔危险
YAML 的卖点是可读:缩进表达嵌套,列表用短横线,标点极少。Kubernetes、GitHub Actions、所有 CI 系统的母语——所以「YAML 转 JSON」通常意思是「把 CI 文件变成机器可读」。
但 YAML 是个带长尾特性的超集,长尾会咬人:
- 挪威问题。
country: NO解析成布尔 false。version: 1.20解析成数字 1.2,软件版本被无声改坏。不加引号的标量会被类型推断,总有一天轮到每个人。 - 锚点与引用(
&anchor、*alias)让一个块引用另一个——大管线去重的利器,而不展开它们的转换器会产出结构错误的 JSON。 - 多文档文件(
---分隔)和多行字符串(|/>家族)携带语义,naive 转换器会把它们抹平。 - 缩进就是结构——从聊天窗口粘贴一块代码,嵌套可能悄悄断裂或合并,而且结果还是合法 YAML。每个 YAML 用户都有这道疤。
正经解析器处理下的 YAML,在大规模人维护的编排文件这个生态位非常出色;正则处理下的 YAML,就是事故的生产方式。
TOML:守规矩的配置文件
TOML 反向下注:让一切结构显式。表是 [section],键值一眼可见,日期有原生类型,任何一个东西只有一种写法——没有类型推断惊喜,没有「空白即结构」。Rust 生态、Python 的 pyproject.toml、Cargo 都因为同一个理由标准化了它:三个不同解析器读同一个 TOML,读到的是同一个文件。
代价是深层的啰嗦:深层嵌套变成 [a.b.c] 的连环标题,巨大重复结构写起来很烦。TOML 为人小心编辑的文件优化,不为任意数据载荷——而那恰恰就是「配置」的定义。
互转的坑
三者之间的转换是损耗边界的谈判,知道哪个方向”安全”能省几小时调试:
- YAML → JSON 是最安全的方向,前提是转换器正确展开锚点/引用和多文档。坑:YAML 不加引号的
on、off、yes——会做类型推断的转换器会愉快地把你的分支名变成true。 - JSON → YAML 结构无损(YAML 能表达全部 JSON——JSON 本来就是合法 YAML),但你会在再解析时收获 YAML 的类型推断怪癖:长得像数字、版本号、布尔词的东西都加引号。
- JSON → TOML 会撞上 TOML 的严格类型:JSON 的混合类型数组(
[1, "a", true])在 TOML 里非法——转换器要么诚实地报错,要么把值转成字符串(下游类型全坏)。深层嵌套的 JSON 也会变成难看的标题链。 - TOML → JSON 干净——TOML 的显式性直接映射;唯一细节是 TOML 的原生 datetime 类型,JSON 里只能表达成字符串(保持 ISO 格式,否则语义丢失)。
我们的转换器(JSON 转 YAML、YAML 转 JSON、JSON 转 TOML,以及 JSON、YAML、TOML 的格式指南)用真解析器——从不用正则——而且全部浏览器本地运行,这里这点比平时更重要:配置文件里常有基础设施拓扑、内网主机名和密钥。「粘贴你的 Kubernetes YAML」类网站是泄露通道;在你自己的浏览器里转换不是。
到底用哪个
- 构建 API 或一切机器对机器 → JSON,没有悬念。
- CI/CD、Kubernetes、DevOps 生态的一切 → YAML——生态已经替你决定了。
- 人手维护的应用配置(Rust、Python、Go 项目)→ TOML。
- 互转 → 用真解析器,歧义标量加引号,另一侧重新校验类型。
FAQ
YAML 是合法 JSON 吗?
不是——但反方向成立:每份 JSON 文档都是合法 YAML(JSON 早期是 YAML 子集,现代 YAML 解析器仍可解析)。这条单行道就是「JSON → YAML 无脑可用、反方向必须上真解析器」的原因。
为什么转换后我的版本号变了?
YAML 对不加引号的标量做类型推断:1.20 变浮点数 1.2,1.0 可能变 1。源头就给版本字符串加引号(version: "1.20"),或者用保留原始标量文本的转换器。
TOML 能表达全部 JSON 吗?
不能。TOML 禁止混合类型数组,JSON 的任意嵌套深度虽合法但会变成 [a.b.c.d] 的标题链地狱。转换器要么拒绝这类结构,要么强制转换类型——看清你的转换器干了什么,别假设映射干净。
配置格式为什么需要注释?
因为配置编码的是决定(「这个超时 30 秒是因为上游的 p99」),没有上下文的决定会被下一个人”修复”。JSON 无注释设计是最被怨恨的特性;YAML 和 TOML 都有一等公民的注释。
现在就试——免费,直接在浏览器里
本指南提到的所有功能都在本站本地运行:不上传、无水印、无需注册。
格式深度解析: JSON (.json) , YAML (.yml.yaml) , TOML (.toml)