正如 YAML语言 官方定义(YAML Ain't Markup Language)一样,YAML 是一种以数据为中心、使用空格、缩进、分行组织数据的简洁的易于读写的具有通用数据序列化格式的非标记语言,目前 YAML语言 官方最新语法标准是 YAML 1.2 (3rd Edition) ") 。

阅读文章的过程中如果有任何疑问,欢迎添加笔者为好友,拉您进【七日书摘】微信交流群,一起交流技术,一起打造高质量的职场技术交流圈子,抱团取暖,共同进步。
七日书摘官方群.jpg

相比我们开发中常用的 inixmlJOSN 以及 properties 格式文件,YAML 利用空格、缩进以及分行,用于显示了数据的结构性,大大的简化了书写格式,降低了复杂度,并提升了易读性。

本文中提供的示例代码均可拷贝到 js-yaml 运行验证。

基本语法规则

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进不允许使用 Tab 键,只允许使用空格
  • 缩进时空格数不重要,只要相同层级的元素左侧对其即可
  • 使用 # 表示注释,即从这个字符一直到行尾,都会被解析器忽略
  • 字符串可以不使用引号标注

YAML文件组织结构

YAML 文件可以由一个或多个文档组成(即相对独立的组织结构组成),一个完整的文档使用 “---” (三个横线)作为文档开始分隔符 和 “...” (三个点号)作为文档结束符(可选);同时如果 YAML 文件只是单个文档,文档开始分隔符 “---” 也可以省略。

YAML 作为单个文档时示例:
server:
  port: 8088 #服务端口
  error:
    path: /404.html #错误页面
YAML 文件由多个文档组成时示例:
server:
  port: 8088 #服务端口
  error:
    path: /404.html #错误页面

--- #database config
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver #JDBC驱动程序
    username: root  #访问数据库账号
    password: xxxxxx  #访问数据库密码

...

--- #dev
spring:
  banner:
    charset: UTF-8  #设置Spring Boot 启动时的banner字符集
    image:
      width: 300

--- #custom config
name: syble #自定义配置项
age: 18

三种数据类型

YAML支持纯量、对象、数组三种数据类型:

  1. 纯量(Scalars):可以用编程语言中的常量/字面量理解,指基本类型的、不可再分隔的值。
  2. 对象:指键值对的集合,又称为映射(Mapping)/哈希(Hashes)/字典(Dictionary)。
  3. 数据:指一组按次序排列的指,又称为序列(Sequence)/列表(List)。
YAML 纯量(Scalars)

YAML 中的纯量包含整数、浮点数、字符串、Null、布尔值、时间、日期。

代码示例如下:

#数值直接以字面量的形式表示。
int:
 - 123
 - 032 #支持二进制/八进制/十六进制表示,以0b-开头表示二进制、0-开始表示八进制、0x-十六进制
float:
 - 2.14
 - 3.14159e+10 #支持科学计数法
string: #字符串的基本用法
 - app.yml #字符串默认不使用引号表示
 - 'application.yml'
 - "application.properties" #字符串可以使用单引号、双引号
 - "I'm a space example." #如果字符串之中包含空格或特殊字符,需要放在引号之中
 - line1
   new line #字符串可以换行,从第二行开始必须有一个单空格缩进。运行后换行符会被转为空格。
null:
 - node: newNode1
 - parent: ~ #null用~表示。
#布尔值用true和false表示。
boolean: #大小写均可
 - TRUE 
 - true
 - True
 - TRUE
 - false
 - False
 - FALSE
#时间采用 ISO8601 格式,日期和时间之间使用 T 连接,最后使用 +代表时区
timestamp: 
 canonical: 2001-12-15T02:59:43.1Z
 valid iso8601: 2001-12-14t21:59:43.10-05:00
 space separated: 2001-12-14 21:59:43.10 -5
 no time zone (Z): 2001-12-15 2:59:43.10
#日期采用 ISO8601 格式,用年、月、日表示,即 yyyy-MM-dd。
date: 
 - 2020-01-05

js-yaml 运行结果如下:

纯量代码运行结果

字符串扩展示例1:单引号和双引号都可以用于定义字符串,但是双引号定义字符串时不会对特殊字符进行转义。
string1: #示例1
 - abcd
 - '测试\n\t例子'
 - "测试\n\t例子"

string2: #示例2
 s1: '测试\n\t例子'
 s2: "测试\n\t例子"

js-yaml 运行结果如下:

字符串扩展示例1

字符串扩展示例2:单引号之中如果还有单引号,必须连续使用两个单引号进行转义。

string3: 'I''m a RD.'

js-yaml 运行结果如下:

字符串特殊示例2

字符串扩展示例3:多行字符串可以使用 | 保留换行符,也可以使用 > 折叠换行。
string4: |
 Foo
 Bar
string5: >
 Foo
 Bar

js-yaml 运行结果如下:

字符串扩展示例3

字符串扩展示例4: + 表示保留文字块末尾的换行, - 表示删除字符串末尾的换行。
string6: |
 Foo
 
string7: |+
 Foo
 
string8: |-
 Foo
  
string9:
 Bar

js-yaml 运行结果如下:

字符串扩展示例4

字符串扩展示例5:字符串之中可以插入 HTML 代码片段
html: |
 <p style="color: red">
 这是html内容
 </p>

js-yaml 运行结果如下:

字符串扩展示例5

YAML 对象

YAML 对象键值对使用冒号结构表示 Key: value冒号后面要加一个空格; 也支持降所有键值对写成一个行内对象 key:{key1: value1, key2: value2, ...},还可以使用缩进表示层级关系。

foo: the object
personal: { name: Steve, age: 30, favorite: football } 
root: 
 child-key: value
 child-key2: value2
 child-key3:
  child-key31: value31
#较为复杂的对象格式,可以使用问号加一个空格代表一个复杂的 key,配合一个冒号加一个空格代表一个 value;意思即对象的属性是一个数组 [complexkey1,complexkey2],对应的值也是一个数组 [complexvalue1,complexvalue2]
? 
 - complexkey1
 - complexkey2
: 
 - complexvalue1
 - complexvalue2

js-yaml 运行结果如下:

YAML 对象

YAML 数组
1. 以 - 开头的行构成一个数组。

YAML数组
js-yaml 运行结果为:[ 'item1', 'item2', 'item3' ]

2. 行内表示法 key: [value1, value2, ...] 构成一个数组。
arrKey1: [item1, item2, item3]
arrKey2: [item1, item2, item3]

js-yaml 运行结果为:

{ arrKey1: [ 'item1', 'item2', 'item3' ],
  arrKey2: [ 'item1', 'item2', 'item3' ] }
3. 数据结构中的子成员是一个数组时可以在该项下面缩进一个空格构成多维数组。

多维数组
js-yaml 运行结果为:

[ [ 'item1', 'item2', 'item3' ],
  [ 'item1', 'item2', 'item3', 'item4' ],
  [ 'item1' ] ]

另外: YAML 中允许使用两个感叹号,强制转换数据类型。示例代码如下:

int: 
 !!int "12"

bool: 
 !!bool "True"
 
string: 
 !!str 3.14

js-yaml 运行结果为:

{ int: 12, bool: true, string: '3.14' }

YAML 复合结构

在 YAML 中对象和数组可以结合使用,形成复合结构。

languages:
 - Ruby
 - Perl
 - Python
companies: 
 -
  id: 1
  name: company1
 - 
  id: 2
  name: company2
blog: 
 url: www.qirishuzhai.com 
 title: 七日书摘 
 author: saiyueze 

js-yaml 运行结果为:

{ languages: [ 'Ruby', 'Perl', 'Python' ],
  companies: [ { id: 1, name: 'company1' }, { id: 2, name: 'company2' } ],
  blog: { url: 'www.qirishuzhai.com', title: '七日书摘', author: 'saiyueze' } }
YAML 锚点、内容合并和引用

在 YAML 中需要使用重复的内容时,可以通过 & 定义锚点、 * 引用锚点以及 << 合并引用锚点内容达到只定义一次实现内容复用的效果。

merge: 
 - &CENTER { x: 1, y: 2 } #创建CENTER锚点
 - &LEFT { x: 0, y: 2 } #创建LEFT锚点
 - &BIG { r: 10 } #创建BIG锚点
 - &SMALL { r: 1 } #创建SMALL锚点
 # All the following maps are equal:
 - # Explicit keys
  x: 1
  y: 2
  r: 10
  label: nothing
 - # Merge one map
  << : *CENTER #<<合并*引用的锚点CENTER内容
  r: 10
  label: center
 - # Merge multiple maps
  << : [ *CENTER, *BIG ] #<<合并*引用的锚点CENTER、BIG内容
  label: center/big
 - # Override
  << : [ *BIG, *LEFT, *SMALL ] #<<合并*引用的锚点CENTER、LEFT、SMALL内容
  x: 1
  label: big/left/small

js-yaml 运行结果为:

{ merge: 
   [ { x: 1, y: 2 },
     { x: 0, y: 2 },
     { r: 10 },
     { r: 1 },
     { x: 1, y: 2, r: 10, label: 'nothing' },
     { x: 1, y: 2, r: 10, label: 'center' },
     { x: 1, y: 2, r: 10, label: 'center/big' },
     { r: 10, x: 1, y: 2, label: 'big/left/small' } ] }

------完------

更多学习讨论欢迎进入七日书摘官方群: 七日书摘官方群

七日书摘官方群群聊二维码.png

参考连接:
https://yaml.org/
https://github.com/yaml/www.yaml.org
http://www.ruanyifeng.com/blog/2016/07/yaml.html