YAML 1.1 和 YAML 1.2 是 YAML 的两个主要版本,它们之间存在一些重要的差异,了解这些差异对于正确使用 YAML 非常重要。
版本历史
YAML 1.1
- 发布于 2005 年
- 被广泛采用,是许多工具和库的默认版本
- 与 JSON 有很好的兼容性
YAML 1.2
- 发布于 2009 年
- 旨在与 JSON 完全兼容
- 简化了语法规则,提高了可预测性
- 解决了 YAML 1.1 中的一些歧义问题
主要差异
1. 类型推断规则
YAML 1.1
yaml# YAML 1.1 会将这些值推断为特定类型 yes: yes # 布尔值 true no: no # 布尔值 false on: on # 布尔值 true off: off # 布尔值 false 123_456: 123_456 # 数字 123456 0b1010: 0b1010 # 二进制数字 10 0o755: 0o755 # 八进制数字 493 0x1F: 0x1F # 十六进制数字 31
YAML 1.2
yaml# YAML 1.2 的类型推断更严格 yes: "yes" # 需要引号才能作为字符串 no: "no" # 需要引号才能作为字符串 on: "on" # 需要引号才能作为字符串 off: "off" # 需要引号才能作为字符串 123_456: 123_456 # 数字 123456(保留) 0b1010: 0b1010 # 二进制数字 10(保留) 0o755: 0o755 # 八进制数字 493(保留) 0x1F: 0x1F # 十六进制数字 31(保留)
2. 布尔值表示
YAML 1.1
支持更多的布尔值表示:
true,falseyes,noon,off
YAML 1.2
只支持:
true,false- 其他值需要显式指定类型或使用引号
3. 八进制表示法
YAML 1.1
yaml# 以 0 开头的数字被解释为八进制 port: 0808 # 八进制,等于十进制的 520
YAML 1.2
yaml# 以 0 开头的数字被解释为十进制 port: 0808 # 十进制 808(如果解析器支持) # 或者使用明确的八进制表示 port: 0o755 # 八进制 493
4. 标签解析
YAML 1.1
yaml# !! 标签用于类型转换 value: !!str 123 # 字符串 "123" date: !!timestamp 2024-01-01
YAML 1.2
yaml# 标签系统更加标准化 value: !!str 123 # 字符串 "123" date: !!timestamp 2024-01-01 # 新增更多标准标签 binary: !!binary SGVsbG8=
5. 转义字符
YAML 1.1
yaml# 支持更多转义字符 text: "\x41" # 十六进制字符 text: "\u0041" # Unicode 字符
YAML 1.2
yaml# 转义字符更加标准化 text: "\x41" # 十六进制字符 text: "\u0041" # Unicode 字符 text: "\U00000041" # 扩展 Unicode
6. 流样式
YAML 1.1
yaml# 流样式中的集合 list: [a, b, c] map: {key: value, key2: value2}
YAML 1.2
yaml# 流样式更加灵活 list: [a, b, c] map: {key: value, key2: value2} # 支持嵌套流样式 nested: [a, [b, c], {key: value}]
兼容性问题
向后兼容性
YAML 1.2 旨在与 YAML 1.1 保持向后兼容,但存在一些例外:
yaml# YAML 1.1 中 yes 是布尔值 true enabled: yes # YAML 1.2 中 yes 可能被解释为字符串 # 需要使用引号或明确指定类型 enabled: "yes" enabled: !!bool yes
JSON 兼容性
YAML 1.2 与 JSON 的兼容性更好:
yaml# 有效的 JSON 也是有效的 YAML 1.2 { "name": "John", "age": 30, "active": true }
实际影响
1. 配置文件解析
yaml# 在不同版本中可能有不同解释 mode: 0755 # YAML 1.1: 八进制 493,YAML 1.2: 十进制 755
2. 布尔值配置
yaml# 可能导致意外的类型转换 debug: yes # YAML 1.1: true,YAML 1.2: 可能是字符串
3. 数字格式
yaml# 数字格式在不同版本中可能有不同解释 port: 0808 # YAML 1.1: 520(八进制),YAML 1.2: 808(十进制)
版本检测
在文档中指定版本
yaml%YAML 1.2 --- # YAML 1.2 内容
在代码中指定版本
Python (PyYAML):
pythonimport yaml # 默认使用 YAML 1.1 data = yaml.safe_load(open('config.yaml')) # 使用 YAML 1.2(需要 ruamel.yaml) from ruamel.yaml import YAML yaml = YAML(typ='safe', version=(1, 2)) data = yaml.load(open('config.yaml'))
JavaScript (js-yaml):
javascriptconst yaml = require('js-yaml'); // 默认支持 YAML 1.2 const data = yaml.safeLoad(fs.readFileSync('config.yaml', 'utf8'));
最佳实践
- 明确指定版本:在 YAML 文件开头声明版本
- 使用引号:对于可能有歧义的值,使用引号明确指定为字符串
- 测试兼容性:确保配置在不同解析器中行为一致
- 文档化:记录使用的 YAML 版本和特殊配置
- 验证工具:使用 YAML linter 验证配置文件
迁移指南
从 YAML 1.1 迁移到 1.2
-
检查布尔值:
yaml# YAML 1.1 enabled: yes # YAML 1.2 enabled: true # 或 enabled: "yes" -
检查八进制数字:
yaml# YAML 1.1 mode: 0755 # YAML 1.2 mode: 0o755 -
检查类型推断:
yaml# YAML 1.1 value: on # YAML 1.2 value: true # 或 value: "on"
工具支持
YAML 1.1 解析器
- PyYAML (Python)
- SnakeYAML (Java)
- LibYAML (C)
YAML 1.2 解析器
- ruamel.yaml (Python)
- js-yaml (JavaScript)
- yaml-cpp (C++)
选择合适的解析器版本对于确保配置正确解析非常重要。