入门:定位、语法骨架与选型
基于 TOML 1.0.0 · 核于 2026-07
速查
- 定位:TOML = Tom's Obvious Minimal Language,一门「面向人类」的配置文件格式;目标是语义显而易见、无歧义映射到哈希表(字典/对象)。由 Tom Preston-Werner 发起,1.0.0 于 2021-01 发布,为当前事实标准。
- 最小单位:键值对
键 = 值;键、=、值必须在同一行,=两侧空白忽略。 - 注释:
#到行尾(字符串内的#除外);没有//、/* */。 - 大小写敏感:
Name与name是两个不同的键。 - 空白/缩进无语义:层级由
[表头]与点分键显式表达,不像 YAML 靠缩进——这是 TOML 相对 YAML 的关键区别。 - 值类型:字符串、整数、浮点、布尔(
true/false)、四种日期时间、数组[ ]、表[table]、内联表{ }、表数组[[array]]。 - 字符串必须加引号:
"双引号"(基本,支持转义)或'单引号'(字面,不转义);这是与 YAML「裸词也算字符串」的重要差异。 - 布尔/特殊值全小写:
true/false、inf/nan,True/Yes/NaN均非法。 - 表
[server]:声明一张表,之后的键值对都归属它;表数组[[products]]:每出现一次追加一个表元素。 - 文件编码:UTF-8;换行 LF 或 CRLF;扩展名
.toml。 - ⚠️ vs JSON:TOML 有注释、有原生日期、键可裸写;JSON 无注释、无日期、键必双引号——JSON 更适合机器交换,TOML 更适合手写配置。
- ⚠️ vs YAML:TOML 空白无语义、无隐式类型转换(无「挪威问题」);YAML 更紧凑但缩进敏感、隐式转换坑多。
- 进阶顺序:本页 → 键与字符串 → 标量与数组 → 表·表数组·内联表 → 生态与常见坑 → 参考。
一、TOML 是什么:定位与设计目标
TOML 是 Tom's Obvious Minimal Language 的缩写,由 GitHub 联合创始人 Tom Preston-Werner 于 2013 年发起,官方口号是「一门面向人类的配置文件格式」。它专注做一件事:把配置写得清晰、可读、可批注,同时保证能被机器唯一确定地解析。
它的两个核心设计目标是:
- 语义显而易见(Obvious):语法收窄、刻意「极简」,不给「一份文档两种解读」留余地。
- 无歧义映射到哈希表(hash table):任何合法 TOML 都能被明确、唯一地解析成一个键值嵌套结构(字典/对象),方便各种语言解析成原生数据结构。
它不是什么
TOML 是纯配置格式:没有函数、变量、循环、引用/锚点等编程能力(这点它比 YAML 更「克制」),也不是通用的数据交换协议(那是 JSON 的主场)。
二、语法骨架
一份 TOML 文档由键值对、注释和表三类要素构成:
toml
# 这是一整行注释
title = "TOML 示例" # 行尾注释
# 键值对:键 = 值,必须写在同一行
name = "Tom"
port = 8080
enabled = true
# 表:[表头] 之后的键值对都归属这张表
[server]
host = "localhost"
port = 5432要点:
- 键值对是最小积木,形式为
键 = 值;键、等号、值必须在同一行,=两侧空白被忽略。 - 注释用
#,从它开始到行尾都被忽略(字符串内部的#不算注释)。TOML 没有//或块注释。 - 大小写敏感:
Name和name是两个不同的键,可以共存。 - 缩进无语义:上例即使给键值对加任意缩进,解析结果不变——层级只由
[server]这样的表头决定。
三、值有哪些类型(速览)
TOML 是强类型格式,值不加引号时会按字面推断类型:
toml
str1 = "双引号:基本字符串"
str2 = '单引号:字面字符串,不转义'
int = 42
float = 3.14
bool = true
date = 1979-05-27T07:32:00Z # 原生日期时间,无需引号
array = [1, 2, 3] # 数组
inline = { x = 1, y = 2 } # 内联表- 无引号、无小数点的数字是整数;带小数点/指数是浮点。
true/false是布尔,且必须小写。- 形如
1979-05-27T07:32:00Z的是日期时间(原生类型,不是字符串)——这是 TOML 相对 JSON 的一大优势。 - 方括号
[ ]包裹一组值是数组;花括号{ }是内联表。
各类型的细节(四种字符串、整数进制、inf/nan、四种日期时间、数组)见标量与数组。
四、与 JSON / YAML / INI 对比选型
TOML、JSON、YAML 常被拿来比较,它们各有主场:
| 维度 | TOML | JSON | YAML |
|---|---|---|---|
| 主要定位 | 手写配置文件 | 机器数据交换 | 手写配置 / 复杂数据 |
| 注释 | ✅ # | ❌ 标准不支持 | ✅ # |
| 层级表达 | [表头] / 点分键(显式) | { } 嵌套 | 缩进(空白敏感) |
| 缩进语义 | 无(空白忽略) | 无 | 有(错一格就变结构) |
| 原生日期时间 | ✅ 四种 | ❌(只能用字符串) | ✅(时间戳) |
| 隐式类型转换 | 无(yes/no 不是布尔) | 无 | 有(挪威问题等坑) |
| 引用/锚点/变量 | ❌ | ❌ | ✅ 锚点 &/别名 * |
| 典型场景 | Cargo.toml、pyproject.toml | REST API、package.json | k8s / CI / Ansible |
一句话选型:
- 需要人手编辑、含注释与日期、层级不太深的应用配置 → TOML 最舒服。
- 需要机器间传输结构化数据、与 Web API 无缝对接 → JSON。
- 需要大量深层嵌套、锚点复用(如 Kubernetes、CI 流水线)→ YAML(但要小心缩进与隐式转换)。
- TOML 也可以看作 INI 的形式化升级:
[section]的直觉一脉相承,但补上了类型系统、嵌套与严格规范。
别把 YAML 的直觉带进 TOML
YAML 老手常犯两个错:一是以为缩进能表达层级(TOML 里缩进被忽略,要用 [表头]);二是写 enabled = yes 当布尔(TOML 只认 true/false,yes 会被当字符串——但字符串还得加引号,所以其实直接报错)。
打好地基后,下一步进入 键与字符串:裸键 / 引号键 / 点分键的规则与冲突,以及四种字符串(基本、多行基本、字面、多行字面)的转义差异。