1. YAML 是啥
YAML 官方解释:YAML Ain’t Markup Language,即 YAML 不是标记语言。
YAML 是一个可以用于所有编程语言的可读性非常好的序列化标准。YAML 广泛用于配置文件。
已经实现 YAML 的语言有:Ruby,Java,Perl,Python,PHP,JavaScript。
2. YAML、XML 及 JSON
YAML 有以下优点:
- 可读性好
- 易于手工维护
- 和脚本语言的交互性好
- 使用实现语言的数据类型(确定是难以跨语言交互数据)
- 可以基于流来处理
- 解析效率高
2.1 XML 和 YAML
XML 解析效率比 YAML 低,但是 XML 支持自定义的数据类型,有大量额外的工具来验证它的格式。
XML 和 YAML 之间没有直接的关联。
YAML 主要是一种数据序列化语言。XML 旨在向后兼容支持结构化文档的标准通用标记语言(Standard Generalized Markup Language,SGML)。 因此,XML 有许多设计限制。XML 是许多领域的先驱,YAML 从 XML 和其他技术中汲取经验教训。
2.2 JSON 和 YAML
JSON 中使用了 {}
和 []
,难以手工维护 JSON 文件,而 YAML 使用空格缩进,既易读又易维护。
JSON 和 YAML 都旨在成为人类可读的数据交换格式。但是,JSON 最重要的设计目标是简单和通用性,并以减少可读性为代价实现这个目的。
YAML 最重要的设计目标是可读性和对序列化任意本地数据结构的支持。因此,YAML 文件非常易读,但是生成和解析过程变得更复杂。另外,在不同编程环境之间交叉使用 YAML 需要更复杂的处理,所以如果跨语言交互数据,请使用 JSON。
YAML 可以被视为 JSON 的超集,提供更优的可读性和更完整的信息模型。实际情况也是如此,每个 JSON 文件也是一个有效的 YAML 文件。如果有需要,可以轻松地从 JSON 迁移到 YAML。
3. 语法
3.1 字符编码及文档分隔
YAML 使用可打印的 Unicode 字符(即非控制字符),支持 UTF-8 和 UTF-16 两种编码。
YAML 使用三个破折号(“—”)将分隔文档中的指令。如果没有指令存在,这也用于指示文档的开始。三个点(“…”)表示文档的结束,表示通信通道中不会再有新文档了。
例如,一个文件中的两个文档:
# Ranking of 1998 home runs
---
- Mark McGwire
- Sammy Sosa
- Ken Griffey
# Team ranking
---
- Chicago Cubs
- St Louis Cardinals
3.2 基本语法规则
- 大小写敏感。
- 使用空格缩进表示层级关系,相同层级的元素左侧有相同个空格。缩进时不允许使用 Tab,只允许使用空格。
#
表示注释,从这个字符一直到行尾,都会被解析器忽略。- 对象的键值对用冒号加空格表示
key: value
。 - 数组列表用破折号加空格(a dash and space)表示:
- break: lunch
3.3 数据结构
YAML 支持的数据结构有三种。
- 对象:键值对集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)。
- 数组:一组按序排列的值,又称为序列(sequence) / 列表(list)。
- 标量:scalars,单个的、不可再分的值,即使是字符串也可以不用引号。用单引号或者双引号括起来的被当作字符串数据,在单引号或双引号中使用 C 风格的转义字符。
3.3.1 对象
对象由键值对组成,使用冒号分隔。
标量组成的对象:
hr: 65 # 相当于 JSON 的 {"hr":65}
YAML 也允许将所有键值对写成一个行内对象:
people: { name: Steve, age: 30 } # 相当于 JSON 的 {"people":{"name":"Steve", "age":30}}
3.3.2 数组
一组相同缩进的破折号开头的行,构成一个数组。例如,标量组成的数组:
- Mark McGwire
- Sammy Sosa
- Ken Griffey
数组可以嵌套:
-
- Mark McGwire
- Sammy Sosa
- Ken Griffey
第一个例子相当于 JSON 中的 [“Mark McGwire”, “Sammy Sosa”, “Ken Griffey”],第二个相当于 [[“Mark McGwire”, “Sammy Sosa”, “Ken Griffey”]]。
跟对象类似,也可以将数组的所有元素写在一行:
people: [Mark, Ken]
3.3.3 标量 Scalars
YAML 中支持的 scaler 类型
- 字符串:在 YAML 中不需要引号,例如:
name: jack
。例外:
- 如果字符串之中包含空格或特殊字符,需要使用单引号或双引号,例如:
name: jack li
- 如果字符串中使用转义字符,则必须使用双引号,例如:
name: "jack line"
- 使用了单引号的字符串中再次出现单引号时,需要用两个单引号转义,例如:
name: 'jack''s name'
- 如果字符串之中包含空格或特殊字符,需要使用单引号或双引号,例如:
- 布尔值:true 或 false,例如:
isAdult: true
- 数值
- 整数:例如:
age: 33
- 浮点数
- 整数:例如:
- Null:在 YAML 中用
~
表示,例如:name: ~
- 时间:时间采用 ISO8601 格式。
iso8601: 2001-12-14t21:59:43.10-05:00
- 日期:日期采用复合 ISO8601 格式的年、月、日表示。
date: 1976-07-31
强制类型转换
YAML 使用两个感叹号强制转换数据类型:
name: !!str true # 相当于 JSON 的 {"name":"true"}
3.4 引用
&
用来建立锚点(defaults),需要同时指定锚点的名字。<<
表示合并到当前数据,*
用来通过名字引用锚点。示例:
# 相当于 JSON 的 [ { x: 1, y: 2 }, { x: 1, y: 2, r: 10, label: 'center' } ]
- &CENTER { x: 1, y: 2 }
- # Merge one map
<< : *CENTER
r: 10
label: center