1. 程式人生 > 實用技巧 >YAML語法

YAML語法

YAML 語法

0.線上工具:yaml 校驗工具

  • yaml 轉 JS

http://nodeca.github.io/js-yaml/

  • yaml 轉 json(格式互轉)

http://www.bejson.com/json/json2yaml/

  • yaml 線上編輯

https://www.bejson.com/validators/yaml_editor/

  • json 格式轉換

https://www.json.cn/

1.簡介

  • 在資料格式描述和較複雜資料內容展示方面的配置檔案,JSON 能夠很好的支援,包括語法突出顯示、自動格式化、驗證工具等。但是 無法註釋,過於嚴格,長字串轉換會出現問題所以 YAML 可以很好的解決這些問題

  • YAML 是 "YAML Ain't a Markup Language"(YAML 不是一種標記語言)的遞迴縮寫,幾乎是 JSON 的超集,已經被用在一些著名的專案中,如 Travis CI、Circle CI 和 AWS CloudFormation。

  • YAML 語言(發音 /ˈjæməl/ )的設計目標,就是方便人類讀寫。它實質上是一種通用的資料序列化格式。

  • YAML 的庫幾乎和 JSON 一樣無處不在。除了支援註釋、換行符分隔、多行字串、裸字串和更靈活的型別系統之外,YAML 也支援引用檔案,以避免重複程式碼。

  • YAML 有一個小的怪癖。所有的 YAML 檔案開始行都應該是 ---,這是 YAML 格式的一部分,表明一個檔案的開始。

  • YAML 的配置檔案字尾為 yml 或者 yaml

  • YAML 基本語法規則如下。

大小寫敏感
使用縮排表示層級關係,縮排時只允許使用空格,不允許使用 Tab 鍵
縮排的空格數目不重要,只要相同層級的元素左側對齊即可,建議至少 2 個空格
符號 # 表示註釋,從這個字元一直到行尾,都會被解析器忽略。
  • YAML 支援的資料結構有三種
物件:鍵值對的集合,又稱為對映(mapping)/ 雜湊(hashes) / 字典(dictionary)
陣列:一組按次序排列的值,又稱為序列(sequence) / 列表(list)
純量(scalars):單個的、不可再分的值

2.YAML 物件寫法

2.1.yaml 基礎物件寫法

  • 一組鍵值對使用冒號結構隔開,冒號後面要加一個空格
key: value
  • 例項演示:簡單的示例
---
value0: 'hello World!'
value1: "hello World!"
value2: hello World!
-------------------------------
# 轉為 JavaScript 格式
{ value0: 'hello World!',
  value1: 'hello World!',
  value2: 'hello World!' }

# 轉換為 json 格式
{
  "value0": "hello World!",
  "value1": "hello World!",
  "value2": "hello World!"
}

2.2.單行寫法

  • 使用以下樣式,將所有鍵值對寫成一個行內物件
key: { key1: value1, key2: value2, ...} 
  • 例項演示:
key: { name: zuiyoujie, age: 20 } 

2.3.多行寫法

  • 使用換行和縮排的寫法可以清晰展示層級關係
key: 
  name: zuiyoujie
  age: 20
  • 單行和多行寫法結果一樣,且都可以轉換格式:
# 轉換轉為 JavaScript 格式
{ key: { name: 'zuiyoujie', age: 20 } }

# 轉換為 json 格式
{
  "key": {
    "name": "zuiyoujie",
    "age": 20
  }
}

2.4.複雜物件格式的寫法

  • 使用問號加空格代表一個複雜的 key,使用一個冒號加空格代表一個複雜的 value
  • 意思是物件的屬性是一個數組 [complexkey1,complexkey2],對應的值也是一個數組 [complexvalue1,complexvalue2]
? 
  - complexkey1
  - complexkey2
: 
  - complexvalue1
  - complexvalue2

3.YAML 陣列寫法

3.1.yaml 單個數組寫法

  • 以連字元 - 開頭的行(一組資料)表示構成一個數組:
  • 列表中的所有成員都開始於相同的縮排級別,比如IP列表,省市列表
key: [ value1, value2, ...]
  • 例項演示:yaml 表示一個列表
# 單行寫法:
china: [ 'beijing', 'shanxi', 'hebei' ]

# 多行寫法:
china: 
  - beijing
  - shanxi
  - hebei
----------------------------
# 轉為 JavaScript 格式
{ china: [ 'beijing', 'shanxi', 'hebei' ] }

# 轉為 json 格式
{
  "china": [
    "beijing",
    "shanxi",
    "hebei"
  ]
}

3.2.yaml 多陣列寫法

  • 兩個陣列的例子:相對複雜,yaml 表示列表和字典
# 單行寫法:
china: [ { beijing: 222, tianjin: 333, hebei: 444 },{ shanxi: 222, shandong: 333 } ] 

# 多行寫法:
china:
  - beijing: 222    # 可以在連字元後直接寫引數
    tianjin: 333
    hebei: 444
  -                 # 也可以連字元分隔,換行寫引數
    shanxi: 222
    shandong: 333
--------------------------
# 轉換為js格式
{ china: 
   [ { beijing: 222, tianjin: 333, hebei: 444 },
     { shanxi: 222, shandong: 333 } ] }

# 轉換為 json 格式
{
  "china": [
    {
      "beijing": 222,
      "tianjin": 333,
      "hebei": 444
    },
    {
      "shanxi": 222,
      "shandong": 333
    }
  ]
}
  • 意思是 china 這個陣列包含兩個陣列,陣列元素又是由 beijing,tianjin,hebei 和 shanxi,shandong 兩個陣列組成

3.3.yaml 多維陣列寫法

  • 資料結構的子成員是一個數組,則可以在該項下面縮排一個空格
china: 
  - beijing: 
    - changping: 555
    - haidian: 777
  - shanxi: 
    - xinzhou: 200
      taiyuan: 300      # 同一陣列資料的連字元可以省略
      datong: 
  - hebei:
    - cangzhou: 500
      xiongan:
-------------------------------
# 轉為 JavaScript 格式
{ china: 
   [ { beijing: [ { changping: 555 }, { haidian: 777 } ] },
     { shanxi: [ { xinzhou: 200, taiyuan: 300, datong: null } ] },
     { hebei: [ { cangzhou: 500, xiongan: null } ] } ] }

# 轉換為 json 格式
{
  "china": [
    {
      "beijing": [
        {
          "changping": 555
        },
        {
          "haidian": 777
        }
      ]
    },
    {
      "shanxi": [
        {
          "xinzhou": 200,
          "taiyuan": 300,
          "datong": null
        }
      ]
    },
    {
      "hebei": [
        {
          "cangzhou": 500,
          "xiongan": null
        }
      ]
    }
  ]
}

3.4.YAML 複合結構

  • 陣列和物件可以結合使用,形成複合結構。
languages:      # 值是三個陣列
  - Ruby
  - Perl
  - Python 
websites:       # 值是三個鍵值對,也就是一個列表或者字典
  YAML: yaml.org 
  Ruby: ruby-lang.org 
  Python: python.org 
  Perl: use.perl.org 
  • 轉為 JavaScript 如下
{ languages: [ 'Ruby', 'Perl', 'Python' ],
  websites: 
   { YAML: 'yaml.org',
     Ruby: 'ruby-lang.org',
     Python: 'python.org',
     Perl: 'use.perl.org' } }

4.YAML 純量

  • 純量是最基本的、不可再分的值
字串
布林值
整數
浮點數
Null
時間
日期
  • 使用一個例子來快速瞭解純量的基本使用:
boolean: 
    - TRUE  #true,True都可以
    - FALSE  #false,False都可以
float:
    - 3.14
    - 6.8523015e+5  #可以使用科學計數法
int:
    - 123
    - 0b1010_0111_0100_1010_1110    #二進位制表示
null:
    nodeName: 'node'
    parent: ~  #使用~表示null
string:
    - 哈哈
    - 'Hello world'  #可以使用雙引號或者單引號包裹特殊字元
    - newline
      newline2    #字串可以拆成多行,每一行會被轉化成一個空格
date:
    - 2018-02-17    #日期必須使用ISO 8601格式,即yyyy-MM-dd
datetime: 
    -  2018-02-17T15:02:31+08:00    #時間使用ISO 8601格式,時間和日期之間使用T連線,最後使用+代表時區
-----------------------------
# 轉換為 JavaScript 格式
{ boolean: [ true, false ],
  float: [ 3.14, 685230.15 ],
  int: [ 123, 685230 ],
  null: { nodeName: 'node', parent: null },
  string: [ '哈哈', 'Hello world', 'newline newline2' ],
  date: [ Sat Feb 17 2018 08:00:00 GMT+0800 (中國標準時間) ],
  datetime: [ Sat Feb 17 2018 15:02:31 GMT+0800 (中國標準時間) ] }

# 轉換為 JSON 格式
{
  "boolean": [
    true,
    false
  ],
  "float": [
    3.14,
    685230.15
  ],
  "int": [
    123,
    685230
  ],
  "null": {
    "nodeName": "node",
    "parent": null
  },
  "string": [
    "哈哈",
    "Hello world",
    "newline newline2"
  ],
  "date": [
    "2018-02-17T00:00:00.000Z"
  ],
  "datetime": [
    "2018-02-17T07:02:31.000Z"
  ]
}

5.YAML 處理字串

5.1.預設字串寫法

  • 字串預設可以不加引號
str: 這是一行字串
--------------------------
# 轉為 JavaScript 如下
{ str: '這是一行字串' }

# 轉換為 JSON 格式
{
  "str": "這是一行字串"
}

5.2.YAML 處理特殊字元

  • 如果字串之中包含空格或特殊字元,需要放在引號之中
str: '內容: 字串'
--------------------------
# 轉為 JavaScript 格式
{ str: '內容: 字串' }

# 轉換為 JSON 格式
{
  "str": "內容: 字串"
}

5.3.YAML 處理引號

  • 單引號和雙引號都可以使用,雙引號不會對特殊字元轉義。
s1: '內容\n字串'
s2: "內容\n字串"
--------------------------------
# 轉為 JavaScript 格式
{ s1: '內容\\n字串', s2: '內容\n字串' }

# 轉換為 JSON 格式
{
  "s1": "內容\\n字串",
  "s2": "內容\n字串"
}
  • 單引號之中如果還有單引號,必須連續使用兩個單引號轉義。
str: 'labor''s day' 
-------------------------
# 轉為 JavaScript 格式
{ str: 'labor\'s day' }

# 轉換為 JSON 格式
{
  "str": "labor's day"
}

5.4.YAML處理文字塊(多行字串)

  • 字串可以寫成多行,從第二行開始,必須至少有一個空格縮排,換行符會被轉為空格。
str: 這是一段
  多行
  字串
-----------------------------
# 轉為 JavaScript 格式
{ str: '這是一段 多行 字串' }

# 轉換為 JSON 格式
{
  "str": "這是一段 多行 字串"
}
  • 多行字串使用 | 可以保留後續的每一個換行符,| 後面不能接資料,需要另起一行寫資料
  • 使用 > 標註的文字內容縮排表示的塊,將塊中回車替換為空格,最終連線成一行,大於號 後面可以接資料
  • 使用 |- 刪除字串末尾所有的換行標記(刪掉空行)
  • 使用 |+ 保留字串末尾的所有換行標記,
s1: |       # 保留3個空行,無資料的空行換行標記沒有記錄
 Foo
 Bar
 Noo



s2: >       # 保留3個空行,無資料空行的換行標記沒有記錄
 Foo
 Bar
 Noo


s3: |-      # 保留3個空行,換行標記只在後面有資料的行上進行保留
 Foo
 Bar
 Noo



s4: |+      # 保留3個空行,記錄了3行空資料的換行標記
 Foo



---------------------------------
# 轉為 JavaScript 格式
{ s1: 'Foo\nBar\nNoo\n',
  s2: 'Foo Bar Noo\n',
  s3: 'Foo\nBar\nNoo',
  s4: 'Foo\n\n\n' }

# 轉換為 JSON 格式
{
  "s1": "Foo\nBar\nNoo\n",
  "s2": "Foo Bar Noo\n",
  "s3": "Foo\nBar\nNoo",
  "s4": "Foo\n\n\n"
}

6.其他特殊用法

6.1.YAML 引用

  • 錨點 & 和別名 *,可以用來引用。
  • & 用來建立錨點(defaults_tag),錨點標記後面資料為引用資料
  • << 表示合併到當前資料,
    • 用來引用錨點。
name: &a yaml
book: *a
books: 
  - java
  - *a
  - python

# 相當於
name: yaml
book: yaml
books: 
  - java
  - yaml
  - python
-----------------------------
# 轉為 JavaScript 格式
{ name: 'yaml',
  book: 'yaml',
  books: [ 'java', 'yaml', 'python' ] }

# 轉換為 JSON 格式
{
  "name": "yaml",
  "book": "yaml",
  "books": [
    "java",
    "yaml",
    "python"
  ]
}
  • 下面是另一個例子。
- &showell Steve 
- Clark 
- Brian 
- Oren 
- *showell 
------------------------
# 轉為 JavaScript 格式
[ 'Steve', 'Clark', 'Brian', 'Oren', 'Steve' ]

# 轉換為 JSON 格式
[
  "Steve",
  "Clark",
  "Brian",
  "Oren",
  "Steve"
]

6.2.YAML 轉換資料型別

  • YAML 允許使用兩個感嘆號,可以強制轉換資料型別,

  • 單歎號通常是自定義型別,雙歎號是內建型別。

  • 內建型別列表:

!!int # 整數型別 
!!float # 浮點型別 
!!bool # 布林型別 
!!str # 字串型別 
!!binary # 也是字串型別 
!!timestamp # 日期時間型別 
!!null # 空值 
!!set # 集合 
!!omap,!!pairs # 鍵值列表或物件列表
!!seq # 序列,也是列表 !!map # 鍵值表
  • 例項演示:
test1: 123   # 值為整數
test2: !!str 456 # 整數轉換為字串
test3: true # true 和 false 預設為布林值
test4: !!bool true # 轉換為布林值,轉換前後一致
test5: !!str  true # 轉換為字串
---------------------------------
# 轉為 JavaScript 格式
{ test1: 123,
  test2: '456',
  test3: true,
  test4: true,
  test5: 'true' }

# 轉換為 json 格式
{
  "test1": 123,
  "test2": "456",
  "test3": true,
  "test4": true,
  "test5": "true"
}

6.3.三個句點 ...

  • ... 和 --- 配合使用,在一個配置檔案中代表一個檔案的結束:
---
time: 20:03:20
player: Sammy Sosa
action: strike (miss)
...
---
time: 20:03:47
player: Sammy Sosa
action: grand slam
...

6.4.YAML 處理 HTML 標記

  • 字串之中可以插入 HTML 標記。
message: |

  <p style="color: red">
    段落
  </p>
----------------------------
# 轉為 JavaScript 格式
{ message: '\n<p style="color: red">\n  段落\n</p>\n' }

# 轉換為 JSON 格式
{
  "message": "\n<p style=\"color: red\">\n  段落\n</p>\n"
}

6.5.YAML 對於函式和正則表示式的轉換

  • 這是 JS-YAML 庫特有的功能,可以把函式和正則表示式轉為字串。

https://github.com/nodeca/js-yaml

# example.yml
fn: function () { return 1 }
reg: /test/

解析上面的 yml 檔案的程式碼如下。
var yaml = require('js-yaml');
var fs   = require('fs');

try {
  var doc = yaml.load(
    fs.readFileSync('./example.yml', 'utf8')
  );
  console.log(doc);
} catch (e) {
  console.log(e);
}
  • 從 JavaScript 物件還原到 yaml 檔案的程式碼如下。
var yaml = require('js-yaml');
var fs   = require('fs');

var obj = {
  fn: function () { return 1 },
  reg: /test/
};

try {
  fs.writeFileSync(
    './example.yml',
    yaml.dump(obj),
    'utf8'
  );
} catch (e) {
  console.log(e);
}

參考地址:

https://ansible-tran.readthedocs.io/en/latest/docs/YAMLSyntax.html
https://www.ruanyifeng.com/blog/2016/07/yaml.html
https://www.jianshu.com/p/97222440cd08
https://juejin.im/post/6844903743557746702
https://zhuanlan.zhihu.com/p/75067291