YAML(YAML Ain’t Markup Language™,YAML 不是标记语言)是一种人性化的数据序列化语言,与所有编程语言配合良好,用于日常任务,如配置文件、日志文件、跨语言数据共享和对象持久化。YAML 专注于易于人类阅读,这也是其设计目标中优先级最高的。
YAML 基于 Unicode 字符集,并围绕动态编程语言的常见本地数据类型(如映射、序列和标量)进行设计。目前的规范版本是 YAML 1.2,最新的修订版是 1.2.2(2021年10月1日)。YAML 1.2 的主要重点是使其成为 JSON 的严格超集。
这份YAML语法教程将全面详细地介绍 YAML 的核心语法和结构。
YAML 基于三种基本的数据原语来表示所有数据结构:
块样式(Block Styles)使用缩进来定义作用域。
使用冒号和空格(:)标记每个键/值对。
# 示例 2.2 映射标量到标量 (玩家统计数据)
hr: 65 # Home runs
avg: 0.278 # Batting average
rbi: 147 # Runs Batted In
使用短横线和空格(- )指示每个条目。
# 示例 2.1 标量序列 (棒球运动员)
- Mark McGwire
- Sammy Sosa
- Ken Griffey
YAML 通过缩进处理嵌套结构。
# 示例 2.3 映射标量到序列 (各联盟的棒球俱乐部)
american:
- Boston Red Sox
- Detroit Tigers
- New York Yankees
national:
- New York Mets
- Chicago Cubs
- Atlanta Braves
# 示例 2.4 映射序列 (球员统计数据)
- name: Mark McGwire
hr: 65
avg: 0.278
- name: Sammy Sosa
hr: 63
avg: 0.288
注意: 缩进是 YAML 结构的关键。为保持可移植性,缩进中不得使用 Tab 字符。所有兄弟节点必须使用完全相同的缩进级别。
流样式(Flow Styles)使用显式指示符(Explicit Indicators)而非缩进来指示作用域,这使其类似于 JSON。
[]) 和逗号分隔列表。{}) 和逗号分隔。# 示例 2.5 序列的序列
- [name, hr, avg]
- [Mark McGwire, 65, 0.278]
- [Sammy Sosa, 63, 0.288]
# 示例 2.6 映射的映射
Mark McGwire: {hr: 65, avg: 0.278}
Sammy Sosa: { hr: 63, avg: 0.288 }
标量内容是 YAML 中数据的实际载体。YAML 提供了多种标量样式,旨在平衡可读性和表达能力。
流式标量可以跨多行,但行中断总会被折叠(折叠成空格,除非是转义的换行)。
即无引号的标量,最常用且最具可读性。
# 示例:普通样式
name: Mark McGwire
value: 0.278
url: https://example.com/foo#bar # 可包含冒号,只要其后不跟空格
使用单引号 (') 包裹。如果需要表示单引号本身,则需要重复两次('')。
\ 字符没有特殊含义。# 示例 2.17 引用标量
single: '"Howdy!" he cried.' # 内部双引号不需要转义
quoted: ' # Not a ''comment''.' # 单引号需用两个单引号表示
使用双引号 (") 包裹。这是唯一支持转义序列的样式。
\n (换行)、\t (Tab)、\b (退格)、\" (双引号)。\x41)、16 位 (\u0041)、32 位 (\U00000041)。# 示例 2.17 引用标量
unicode: "Sosa did fine.\u263A"
control: "\b1998\t1999\t2000\n"
hex esc: "\x0d\x0a is \r\n"
块式标量用于处理多行文本。它们使用缩进而不是引号来包围内容。
|)保留所有换行符(包括空行和内部缩进)。
# 示例 2.13 字面量样式:保留换行
---
|
\//||\/||
// ||
||__
# 结果:保留原始结构
# "\//||\/||\n// ||\n||__\n"
>)将换行折叠成单个空格,使得长文本易于阅读。
# 示例 2.14 折叠样式:换行变为空格
---
>
Mark McGwire's year was
crippled by a knee injury.
# 结果:折叠成一行
# "Mark McGwire's year was crippled by a knee injury.\n"
# 示例 2.15 折叠样式:保留空行和更多缩进的行
---
>
Sammy Sosa completed another fine season with great stats.
63 Home Runs
0.288 Batting Average
What a year!
块式标量可以添加一个块标头来控制缩进和尾随换行符的处理,即“Chomping”。
| 或 > (默认/Clip):保留最后的换行符,移除所有尾随空行。|- 或 >- (Strip):移除最后的换行符和所有尾随空行。|+ 或 >+ (Keep):保留最后的换行符和所有尾随空行。# 示例 8.4 Chomping 处理
strip: |-
text
clip: |
text
keep: |+
text
YAML 提供了用于数据重用、类型标记和流控制的机制。
一个 YAML 字符流可以包含零个或多个文档。
---)用于分隔指令和文档内容,或标记文档的开始。...)指示文档结束,常用于通信通道。# 示例 2.7 流中的两个文档
# 1998年本垒打排名
---
- Mark McGwire
- Sammy Sosa
- Ken Griffey
# 球队排名
---
- Chicago Cubs
- St Louis Cardinals
# 示例 2.8 比赛的实时消息
---
time: 20:03:20
player: Sammy Sosa
action: strike (miss)
...
---
time: 20:03:47
player: Sammy Sosa
action: grand slam
...
YAML 能够表示图形结构(Directed Graph),通过锚点(Anchor)和别名(Alias)实现数据重用。
&): 用于标识(&anchor)一个节点。该节点是首次出现。*): 用于引用(*alias)先前锚定的节点。# 示例 2.10 节点 "Sammy Sosa" 出现两次
---
hr:
- Mark McGwire
- &SS Sammy Sosa # 节点被标记为 SS
rbi:
- *SS # 后续引用
- Ken Griffey
注意: 别名节点不能指定任何属性或内容。锚点名称是一个序列化细节,不应用于传达内容信息。
YAML 节点需要一个标签(tag)来指定其数据类型。标签使用感叹号(!)指示。
!,对于所有其他节点(包括集合和普通标量)是 ?。! 开头,特定于单个应用程序。例如 !something。tag:yaml.org,2002:str。< 和 > 包围标签,如 !<tag:yaml.org,2002:str>。| 标签 (Tag Shorthand) | 示例 | 描述 |
|---|---|---|
!!str | '012345', "foo\nbar", plain string | Unicode 字符串。 |
!!int | 12345, 0o14 (八进制), 0xC (十六进制) | 整数。 |
!!float | 1.23015e+3, .inf (正无穷), .nan (非数字) | 浮点数。 |
!!bool | true, false, True (Core Schema) | 布尔值。 |
!!null | null, ~, (空值) | 空值。 |
# 示例 2.23 各种显式标签
---
not-date: !!str 2002-04-28
picture: !!binary |
R0lGODlhDAAMAIQAAP//9/X
17unp5WZmZgAAAOfn515eXv
...
application specific tag: !something |
The semantics of the tag above
may be different for different documents.
指令是给 YAML 处理器(Processor)的指示。指令必须出现在非缩进的行首,以百分号(%)开始。
%YAML 指令指定文档遵循的 YAML 版本。
# 示例 6.14 “ YAML ” 指令
%YAML 1.2
---
document content
%TAG 指令建立标签速记符号(Tag Shorthand),将句柄(Handle)与前缀(Prefix)关联起来,使标签表示更简洁。
!,默认前缀为 !(本地标签)。!!,默认前缀为 tag:yaml.org,2002:。!e!。# 示例 2.24 全局标签
%TAG ! tag:clarkevans.com,2002: # 定义命名句柄 !
---
!shape # 使用 ! 句柄,扩展为全局标签
- !circle
center: &ORIGIN { x: 73, y: 129 }
radius: 7
通常映射的键是标量。当需要使用集合(序列或映射)作为键时,必须使用问号和空格(? )来显式指示键的开始。
# 示例 2.11 序列之间的映射
? - Detroit Tigers
- Chicago cubs
: - 2001-07-23
? [ New York Yankees, Atlanta Braves ]
: [ 2001-07-02, 2001-08-12, 2001-08-14 ]
# 示例 2.25 无序集合 (Sets)
--- !!set
? Mark McGwire
? Sammy Sosa
? Ken Griffey
# 集合被表示为键关联着空值 (null value) 的映射
以下是 YAML 语法的完整示例,展示了前面讨论的各种元素的综合使用。
此示例展示了锚点/别名、块式标量以及显式全局标签的使用。
# 示例 2.27 发票 (Invoice)
--- !<tag:clarkevans.com,2002:invoice>
invoice: 34843
date : 2001-01-23
bill-to: &id001 # 使用锚点 &id001 标记账单地址
given : Chris
family : Dumars
address:
lines: | # 使用字面量块标量,保留换行
458 Walkman Dr.
Suite #292
city : Royal Oak
state : MI
postal : 48046
ship-to: *id001 # 使用别名引用账单地址
product:
- sku : BL394D
quantity : 4
description : Basketball
price : 450.00
- sku : BL4438H
quantity : 1
description : Super Hoop
price : 2392.00
tax : 251.42
total: 4443.52
comments: Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.
此示例展示了多文档流、时间戳(虽然未明确标记,但会被解析器识别)和折叠块式标量。
# 示例 2.28 日志文件 (Log File)
---
Time: 2001-11-23 15:01:42 -5
User: ed
Warning: This is an error message for the log file
---
Time: 2001-11-23 15:02:31 -5
User: ed
Warning: A slightly different error message.
---
Date: 2001-11-23 15:03:17 -5
User: ed
Fatal: Unknown variable "bar"
Stack:
- file: TopClass.py
line: 23
code: | # 字面量样式
x = MoreObject("345\n")
- file: MoreClass.py
line: 58
code: |- # 字面量样式,- 剥离末尾换行
foo = bar
YAML 语言的核心优势在于其人类可读性和与现代编程语言原生数据结构的高度匹配。通过灵活运用块样式和流样式,以及各种标量表示方法,YAML 能够优雅地序列化从简单配置到复杂图形结构的任何数据。