乐闻世界logo
搜索文章和话题

YAML 1.1 和 YAML 1.2 有什么区别?如何处理版本兼容性问题?

2月21日 14:22

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, false
  • yes, no
  • on, 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):

python
import 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):

javascript
const yaml = require('js-yaml'); // 默认支持 YAML 1.2 const data = yaml.safeLoad(fs.readFileSync('config.yaml', 'utf8'));

最佳实践

  1. 明确指定版本:在 YAML 文件开头声明版本
  2. 使用引号:对于可能有歧义的值,使用引号明确指定为字符串
  3. 测试兼容性:确保配置在不同解析器中行为一致
  4. 文档化:记录使用的 YAML 版本和特殊配置
  5. 验证工具:使用 YAML linter 验证配置文件

迁移指南

从 YAML 1.1 迁移到 1.2

  1. 检查布尔值

    yaml
    # YAML 1.1 enabled: yes # YAML 1.2 enabled: true # 或 enabled: "yes"
  2. 检查八进制数字

    yaml
    # YAML 1.1 mode: 0755 # YAML 1.2 mode: 0o755
  3. 检查类型推断

    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++)

选择合适的解析器版本对于确保配置正确解析非常重要。

标签:YAML