TOML 深度调研:对比 YAML、JSON 等五大配置格式,哪种最适合你的项目?

大家好,我是若风。

上周在配置一个 Rust 项目的时候,我盯着 Cargo.toml 发了一会儿呆。然后突然意识到一件事:我写了这么多年代码,跟配置文件打交道的时间可能比写业务逻辑还多。package.jsondocker-compose.ymltsconfig.json.gitignoreterraform.tf......每个项目至少 3 到 5 个配置文件。

但说实话,我从来没认真想过一个问题:为什么这些工具要用不同的配置格式?

YAML 写 Kubernetes 配置,JSON 写 package.json,TOML 写 Cargo.toml,HCL 写 Terraform------这些选择是随机的,还是各有道理?

带着这个疑问,我做了一次深度调研。这篇文章就是调研结果。

先说结论

如果你在为新项目选配置格式,2026 年的默认推荐是 TOML,除非你遇到以下情况:

  1. 场景是数据交换------用 JSON
  2. 工具链强制要求 YAML(如 Kubernetes、GitHub Actions)------用 YAML
  3. 你在写 Terraform------用 HCL

下面展开讲为什么。

TOML 是什么?

TOML 的全称是 Tom's Obvious, Minimal Language------Tom 的显而易见的极简语言。注意,它不是递归缩写,也不是回文;只是一个名字很直白的配置格式。

创建者是 GitHub 联合创始人 Tom Preston-Werner,最早在 2013 年公开。它的设计动机很直接:做一个比 INI 更有类型、比 YAML 更少歧义、比 JSON 更适合人手写的配置格式。

具体来说,Tom 忍不了这几件事:

YAML 规范和生态都比较复杂,很多问题来自旧版 YAML 1.1 规则以及解析器兼容行为:比如 NOyesonoff 可能被解析成布尔值,1:30 在部分旧规则里可能被当作 sexagesimal 数字处理。YAML 1.2 已经收紧了这些隐式类型规则,但现实世界里的解析器和工具链并不总是严格按 1.2 行为走。同一份 YAML 文件在不同语言、不同解析器、不同版本下可能产生不同结果,这是它最让人头疼的地方。

Tom 的目标很清晰:做一个更好版本的 INI。语义明显、无歧义、最小化。能无歧义地映射到哈希表。

TOML 的核心特性

TOML 有一套丰富且严格的类型系统,这是它区别于 INI 的核心优势。

八种数据类型

toml 复制代码
# 字符串------支持四种写法
title = "TOML Example"                    # 基本字符串(支持转义)
path = 'C:\Users\name\docs'               # 字面量字符串(原样输出,不转义)
description = """可以换行的
多行字符串"""
regex = '''I [dw]on't need \d{2} apples''' # 多行字面量字符串

# 整数------支持进制转换和下划线分隔
port = 8080
hex_color = 0xDEAD                         # 十六进制
permissions = 0o755                        # 八进制
big_num = 1_000_000                        # 下划线分隔,提升可读性

# 浮点数------支持 inf 和 nan
pi = 3.14159
special = inf

# 布尔值------只有 true/false,不会搞出什么 yes/no/on/off
debug = true

# 日期时间------四种类型,是 TOML 相对 JSON/INI 更完整的地方
created = 2023-01-11T08:30:00Z            # 带时区
deadline = 2023-12-31T23:59:59            # 不带时区
birthday = 1990-05-27                      # 纯日期
alarm = 07:30:00                           # 纯时间

集合类型

toml 复制代码
# 数组------v1.0/v1.1 允许混合类型,但配置实践中更建议保持同构
ports = [80, 443, 8080]
mixed = ["admin", 42, true]                # 合法,但不一定推荐

# 表(Table)------即字典/哈希表
[database]
server = "192.168.1.1"
ports = [8001, 8001, 8002]

# 嵌套表
[database.connection]
max_open = 100

# 内联表------单行紧凑写法
point = { x = 1, y = 2 }

# 数组表------用双方括号,每个块是数组中的一个元素
[[products]]
name = "Hammer"
sku = 738594937

[[products]]
name = "Nail"
sku = 284758393

这些特性覆盖了配置文件的几乎所有需求。跟 INI 比,功能丰富太多了;跟 YAML 比,每一条的语义都是明确的,没有隐式推断。

TOML 的版本演进

TOML 从 2013 年到现在,经历了一个从快速迭代到稳定规范的过程:

版本 时间 关键变化
v0.1.x 2013 年 初始阶段,确立键值对、表、数组等基础语法
v0.2.x 2013 年 补充日期时间、多行字符串、数组表 [[table]] 等能力
v0.3.x 2014-2015 年 引入点分隔键、内联表等更完整的结构表达
v0.5.0 2018 年 允许混合类型数组,补充十六进制、八进制、二进制整数
v1.0.0 2021 年 1 月 11 日 首个稳定版,成为多数生态的兼容基线
v1.1.0 2025 年 12 月 18 日 当前最新规范 ,增加少量语法便利性,例如 \e\xHH 转义,以及部分日期时间场景可省略秒

截至 2026 年 5 月,TOML v1.1.0 是当前最新规范 。不过很多语言标准库和主流工具仍以 v1.0.0 为兼容基线,例如 Python 3.11+ 标准库 tomllib 明确解析 TOML 1.0.0。因此实际选型时可以这样理解:v1.0.0 是最稳的跨生态底座,v1.1.0 是最新规范方向。

谁在用 TOML?

TOML 的采用不是靠营销,而是靠一个个具体的技术决策。

Rust:Cargo.toml

TOML 与 Rust 生态有很深的渊源。Cargo 使用 Cargo.toml,也是 TOML 获得广泛关注的重要起点。Rust 社区偏好显式和可预测的行为,跟 TOML 的"无歧义"理念很匹配。

Python:pyproject.toml

这是近十年最重要的配置格式迁移案例之一。Python 社区通过一系列 PEP 和 PyPA 规范,把构建系统依赖、项目元数据和工具配置逐步集中到 pyproject.toml。但它不是"一夜之间替代所有遗留文件":setup.pysetup.cfgtox.ini 等文件在大量项目里仍然存在。

迁移路径大致是这样的:

arduino 复制代码
阶段一(2016 前):setup.py + requirements.txt + MANIFEST.in + tox.ini + ...
阶段二(2016-2020):pyproject.toml 先标准化 [build-system],同时保留 setup.py/setup.cfg
阶段三(2020-2024):PEP 621 标准化 [project],更多构建后端和工具迁移进 pyproject.toml
阶段四(2024-2026):pyproject.toml 成为新项目的主配置入口,但遗留文件仍大量存在

Ruff 的成功不只是因为配置文件,但 [tool.ruff] 这种集中式配置确实降低了 Python 项目的工具链复杂度。过去 flake8、isort、Black、mypy、pytest 往往各有配置入口,现在越来越多工具支持把配置放进 pyproject.toml[tool.*] 命名空间里。

其他采用者

项目 配置文件 说明
GoReleaser .goreleaser.toml Go 项目发布自动化
Hugo config.toml 静态网站生成器
Zola config.toml 静态网站生成器
Poetry pyproject.toml Python 包管理
Ruff ruff.toml Python linter/formatter
Taplo --- TOML 工具链(LSP、格式化、验证)

五种格式全面对比

现在进入正题:TOML、YAML、JSON、INI、HCL,到底怎么选?

总览对比

维度 TOML YAML JSON INI HCL
创建年份 2013 2001 2001 ~1980s 2014
规范复杂度 中等 无统一规范 中高
注释 # # 不支持 #; #//
类型系统 丰富 最丰富 基础 丰富
缩进敏感
日期时间 原生支持 支持 不支持 不支持 不支持

可读性排名

YAML > TOML > INI > HCL > JSON

YAML 视觉上最干净,但"看起来简单"不等于"读起来准确"------隐式类型推断是最大的隐患。TOML 结构清晰,[section] 分区直观,类型表示明确。JSON 的引号和逗号噪音太多,作为人类编辑的配置格式体验最差。

解析速度排名

JSON 通常最快,TOML/YAML/HCL 取决于实现和配置复杂度。

JSON 的语法最小,标准库实现也最成熟,所以通常是解析性能基准。TOML 比 JSON 语法更丰富,解析一般会慢一些,但配置文件通常很小,这个差距很少成为选型主因。YAML 因为语法、锚点、标签和隐式类型规则更复杂,解析和安全边界更难控制。HCL 的重点不在"最快解析",而在表达 Terraform 这类领域配置时的结构和表达式能力。

更实际的判断是:如果你在解析 MB 级甚至 GB 级机器生成数据,选 JSON 或二进制格式;如果只是人手写的项目配置,解析性能通常不如可维护性重要。

人类可写性排名

YAML ≈ TOML > INI > HCL > JSON

YAML 写起来最"自由",但也最容易写错。TOML 写起来有约束但可预测------主要痛点是深层嵌套时需要写很多 [section.subsection.deep] 头部。JSON 写配置文件的体验就不用说了,不能写注释这一条就够劝退了。

每种格式的典型陷阱

这部分很实用。每种格式都有自己独特的坑,踩过才知道疼。

TOML 的坑

重复定义和隐式表规则容易踩坑。 TOML 不允许同一个键重复定义,也不允许把已经定义成具体值的键再当表使用。点分隔键可以隐式创建表,但乱序写 dotted key 虽然可能合法,却会降低可读性。

内联表不可扩展。 point = { x = 1, y = 2 } 定义之后,不能再写 point.z = 3

深层嵌套冗长。 这是 TOML 最被诟病的设计问题。五层嵌套的配置写起来会变成 [a.b.c.d.e],跟 YAML 的缩进比确实不够优雅。

YAML 的坑

"挪威问题"------旧版 YAML 规则和解析器兼容行为里的经典陷阱。

yaml 复制代码
countries:
  - NO    # 在 YAML 1.1 / 部分解析器中可能被解析为 false
  - SE    # 通常是字符串 "SE"
  - yes   # 在 YAML 1.1 / 部分解析器中可能被解析为 true
  - on    # 在 YAML 1.1 / 部分解析器中可能被解析为 true

严格说,YAML 1.2 已经把布尔值收敛到更接近 JSON 的 true / false 规则;但很多工具为了兼容旧生态,仍可能保留 YAML 1.1 的隐式布尔行为。这个问题在涉及国家代码、开关名、环境变量值的配置中会突然冒出来,排查起来非常痛苦。

隐式数字解析也容易误伤。 旧规则和部分解析器可能把 12:30 当作 sexagesimal 数字处理,1.0 也可能被当作浮点数而不是字符串。凡是 ID、版本号、时间片段、国家代码这类值,在 YAML 里都建议显式加引号。

安全风险。 在 PyYAML 等库中,使用不安全 Loader 解析不可信 YAML 有反序列化风险。处理外部输入时应该使用 safe_load() 或等价的 SafeLoader;这条规则被人忘了无数次。

JSON 的坑

不支持注释。 这一条就让 JSON 在配置文件场景中极不实用,直接催生了 JSONC 和 JSON5 等超集格式。

尾随逗号禁止。 { "a": 1, "b": 2, } 是语法错误。改配置时加了一行就忘了删逗号,这种低级错误每个人至少犯过 3 次。

不支持真正的多行字符串。 长文本只能写成一行或用 \n 转义,可读性会明显变差。

INI 的坑

无标准规范。 Python 的 configparser、PHP 的 parse_ini_file、Windows 的 GetPrivateProfileString 行为各不相同。同一份 INI 文件在不同环境下可能解析出不同的结果。

无类型系统。 所有值都是字符串,需要应用层自己做类型转换。

选型建议:一张决策图

javascript 复制代码
你的配置文件用途是什么?
│
├─ 数据交换/API 通信 → JSON(默认选择)
│
├─ 基础设施即代码(Terraform)→ HCL
│
├─ DevOps/CI/CD/Kubernetes → YAML(生态强制要求时遵循工具)
│
├─ 应用/项目配置文件
│  ├─ 新项目自由选择 → TOML
│  ├─ 已有工具链要求 → 遵循工具要求
│  └─ 极简配置(几个键值对)→ TOML 或 INI
│
└─ 需要编程逻辑(循环、条件)→ HCL 或考虑 DSL

业界趋势

最后聊聊配置格式的发展方向。

TOML 持续崛起

TOML 正在经历"慢热式"的广泛采用。不是爆发式增长,而是由一个个具体的技术决策推动:Rust 生态的示范效应、Python 包装生态对 pyproject.toml 的持续标准化、以及 Ruff、Poetry、Hatch、uv 等工具的采用,都在扩大 TOML 的日常可见度。编辑器工具链也成熟了------Taplo(TOML LSP)提供自动补全、验证、格式化,开发体验已经比较完整。

"YAML 疲劳"蔓延

DevOps 和云原生社区对 YAML 的不满正在积累。Kubernetes 生态里已经出现了 CDK8s、Pulumi 等用真正编程语言生成配置的替代方案。复杂 YAML 模板(如 Helm Charts)的可维护性问题日益突出。

但 YAML 的生态惯性极强------Kubernetes、GitHub Actions、GitLab CI 等核心工具仍然强制使用 YAML,短期内不会改变。

JSON 超集兴起

JSON 不支持注释这个根本缺陷,催生了 JSONC(VS Code 配置广泛使用)和 JSON5(更宽松的语法)等超集。在 TypeScript 和前端工具生态中,这类"类 JSON 配置"已经很常见。

配置即代码

一个更深层的趋势:当配置复杂到一定程度时,静态的声明式格式都不够用,需要编程语言的抽象能力。Pulumi 用 TypeScript/Python/Go 定义基础设施,AWS CDK 用编程语言生成 CloudFormation 配置,Dhall 和 CUE 是专门设计的可编程配置语言。

写在最后

回头看看这五种配置格式,有一个感受很深:没有完美的配置格式,只有最适合场景的选择。

JSON 是数据交换的通用语言,但不是好的配置格式。YAML 是 DevOps 领域的事实标准,但设计缺陷正在累积技术债。INI 是历史遗留的极简格式,新项目不建议使用。HCL 是基础设施即代码的专用工具,不适用于通用场景。

而 TOML 的设计哲学------"语义明显、最小化、无歧义"------在配置文件领域代表了最健康的平衡点。它没有 INI 的功能贫乏,没有 YAML 的过度工程,也没有 JSON 的注释缺失。

对于新项目,如果你要的是"人手写、机器解析、结构不太复杂"的应用配置,TOML 是 2026 年我会默认推荐的选择。这不是跟风,而是算过账的。

参考来源

相关推荐
wangruofeng1 小时前
Bun 深度调研:一个想把 JavaScript 工具链全部重写的野心项目
ai编程·devops
甲维斯3 小时前
这一波MiMo2.5pro被DeepSeek V4 完虐了!
ai编程
Mac的实验室4 小时前
ChatGPT 突然要验证手机号?2026年登陆注册Codex解决手机号码验证的问题(附最新图文教程解决办法)
ai编程
Mac的实验室4 小时前
2026 最新 Codex 手机号验证教程:国内如何解决 ChatGPT 手机号验证问题
ai编程
Mac的实验室4 小时前
2026年Codex如何解决手机号码登陆验证的问题?
ai编程
Irissgwe4 小时前
LangChain之核心组件(输出解析器)
ai·langchain·llm·ai编程·输出解析器
Mac的实验室4 小时前
为什么用chatgpt账号登入一直提示需要电话号码, 要验证手机号怎么解决?
ai编程
沐泽__5 小时前
自注意力机制含义
ai编程
沐泽__5 小时前
Skill 如何实现(通用思路,可直接用)含义
ai编程