YAML
YAML Ain't Markup Language 的缩写,一种基于缩进的人类可读数据序列化格式。
YAML (YAML Ain't Markup Language) 是一种使用缩进表示层级结构的人类可读数据序列化格式。最初是"Yet Another Markup Language"的缩写,后来为了强调它不是标记语言而改为现在的递归缩写。广泛用于配置文件和数据交换,特别是在 DevOps 领域已成为事实标准。
YAML 在 1.2 版中正式把 JSON 收纳为子集,有效的 JSON 可以原样作为有效的 YAML 读取 (1.1 及之前并非完全兼容)。JSON 没有的特性包括注释 (#)、锚点和别名 (数据复用)、单文件多文档 (用 --- 分隔)、块标量 (多行文本表示) 等。它被广泛用于 Docker Compose、Kubernetes 清单、GitHub Actions 工作流、Ansible 剧本、CloudFormation 模板等 DevOps 工具的配置文件。
YAML 语法有几个值得注意的陷阱。缩进不能使用制表符,只允许空格。另一个是隐式类型转换。1.0 会被读作浮点数,yes、no、on、off 会被转换为布尔值。挪威国家代码 NO 变成 false 的"挪威问题"就是其代表例子。不过这一行为会随版本而变化。把作为布尔值处理的词收敛到 true / false (及其大写形式),是 1.2 版默认的类型解释,Yes 和 No 会被读作字符串。另一方面,实现一侧保留 1.1 解释的很多,在 Python 的 PyYAML 6 系中,yes、no、on、off、NO 全都会变成布尔值 (截至 2026 年实测)。不要只看规范的版次就放心,请在实际使用的解析器上确认。要确保字符串被当作字符串处理,用引号括起来最为可靠。此外重复键也是陷阱。有的实现即使把同一个键写两次也不报错,而是用后面的值覆盖,PyYAML 就是这种行为 (同样为实测)。在很长的配置文件中设置不生效时,请怀疑同一个键是否在下方又写了一遍。
YAML 和 JSON 的选择取决于用途。YAML 适合人类读写的配置文件,能写注释是一大优势。JSON 适合程序间的数据交换,语法简单因而解析器的实现可以做得很小,也不容易发生隐式类型转换那样的解释摇摆。通常的做法是 API 响应用 JSON,CI/CD 配置用 YAML。
从安全角度来看,YAML 反序列化需要注意。某些 YAML 解析器可以生成任意对象,从不受信任的来源加载 YAML 并使用不安全的解析器可能导致远程代码执行漏洞。在 Python 的 PyYAML 中,应使用 yaml.safe_load() 而非 yaml.load()。
从字符计数角度来看,YAML 由于括号和引号较少,字符数往往比 JSON 少;但这是比较对象为带缩进的 JSON 时的情形。用把姓名、年龄和标签数组嵌套一层的同一份数据来数,YAML 是 52 个字符,缩进 2 空格的 JSON 是 95 个字符,压紧空白的 JSON 是 50 个字符 (以 Python 3 实测)。也就是说,若拿易读的形式互相比较,YAML 占优;而与以机器读取为前提、压紧空白的 JSON 则几乎持平。由于 YAML 缩进的空格必然计入字符数,嵌套越深这一差距就越小,甚至会反转。如果在意配置文件的字符数,请先统一比较对象是带缩进还是压紧的形式,再来计数。