YAML の構文を押さえる : 文字列をクォートで囲む必要はない

YAML の構文を改めて勉強。

このサイトで実際に変換しながら確認した。

目次

文字列に関して

以下の Stackoverflow が分かりやすかった。

plain scalars:
- a string
- a string with a \ backslash that doesn't need to be escaped
- can also use " quotes ' and $ a % lot /&?+ of other {} [] stuff

single quoted:
- '& starts with a special character, needs quotes'
- 'this \ backslash also does not need to be escaped'
- 'just like the " double quote'
- 'to express one single quote, use '' two of them'

double quoted:
- "here we can use predefined escape sequences like \t \n \b"
- "or generic escape sequences \x0b \u0041 \U00000041"
- "the double quote \" needs to be escaped"
- "just like the \\ backslash"
- "the single quote ' and other characters must not be escaped"

literal block scalar: |
  a multiline text
  line 2
  line 3

folded block scalar: >
  a long line split into
  several short
  lines for readability

ハッシュ (マップ・連想配列) とリスト (配列)

ハッシュ (マップとか、連想配列とか) は、その階層で key: value を繋げて書けば良い。

hoge: hogeValue
fuga: fugaValue

↓ コレは JSON に変換するとこうなる。

{
  "hoge": "hogeValue",
  "fuga": "fugaValue"
}

リスト (配列) はハイフンとスペースで始める。

- hoge
- fuga

↓ JSON に変換するとこうなる。

[
  "hoge",
  "fuga"
]

ハッシュをリストとして定義。

- hoge: hogeValue
  hogeDescription: This is hoge.
- fuga: fugaValue
  fugaDescription: This is fuga.

↓ JSON に変換するとこう。

[
  {
    "hoge": "hogeValue",
    "hogeDescription": "This is hoge."
  },
  {
    "fuga": "fugaValue",
    "fugaDescription": "This is fuga."
  }
]

ハッシュをネストする時のインデントが若干分かりづらいかもしれない。

- name: My Services 1
  services:
  - name: my-services-1-A
    enabled: true
  - name: my-services-1-B
    enabled: false
- name: My Services 2
  services:
    - name: my-services-2-A
      enabled: false
    - name: my-services-2-B
      enabled: true

services: の配下にある「ハッシュのリスト」は、services の行頭と同じインデントになっていたり、1段階ネストを下げたりしているが、どちらも階層構造は変わらず、次のように JSON 化して表現できる。

[
  {
    "name": "My Services 1",
    "services": [
      {
        "name": "my-services-1-A",
        "enabled": true
      },
      {
        "name": "my-services-1-B",
        "enabled": false
      }
    ]
  },
  {
    "name": "My Services 2",
    "services": [
      {
        "name": "my-services-2-A",
        "enabled": false
      },
      {
        "name": "my-services-2-B",
        "enabled": true
      }
    ]
  }
]

フロースタイル

上述のような書き方をブロックスタイルという。一方、1行にまとめてリストやハッシュを書けるフロースタイルという書き方もある。

nameList1: [Jane Doe, Foo Bar]
nameList2: ['Jane Doe', "Foo, Bar"]
profileHash1: { name: Jane Doe, age: 22 }
profileHash2: { name: "Foo, Bar", age: 30 }

リスト [] とハッシュ {} を1行で書ける。

次のように JSON 変換できる。

{
  "nameList1": [
    "Jane Doe",
    "Foo Bar"
  ],
  "nameList2": [
    "Jane Doe",
    "Foo, Bar"
  ],
  "profileHash1": {
    "name": "Jane Doe",
    "age": 22
  },
  "profileHash2": {
    "name": "Foo, Bar",
    "age": 30
  }
}

パイプ記号 | による複数行リテラル

パイプ記号 | を使うと複数行のテキストを書ける。

first: |
 hoge
   fuga
 foo
  bar
second: | hoge |
third: |fuga|

コレを JSON 化するとこうなる。

{
  "first": "hoge\n  fuga\nfoo\n bar\n",
  "second": "| hoge |",
  "third": "|fuga|"
}

first: | の次の行、hoge は1つ以上のスペースを開けて書く。大抵は2スペースを開けて書くことが多いかな。コレがインデントの始点となり、以降の行に登場する先頭のスペースは無視される。その証拠に、JSON データを見ると、foohoge と同じスペース数なので、行頭にスペースがない。一方、fugabar の行は行頭に hoge 以上のスペースがあるので、それが残っている。

secondthird は、いきなりパイプ記号 | を使ったとしても、その後に改行 + インデントが登場しなければ単に文字列として認識されるという例。なんだかこの辺の解釈が優秀すぎて、覚えきれないんだよなぁ。思ったとおりに解釈されているのかが JSON よりも不安な感じ。w

大なり記号 > による折りたたみスタイル

大なり記号 > を使うと、複数行で書いたテキストも1行にまとめてくれる。

single-data: >
  aaa
  bbb
  ccc
    ddd
  eee

JSON 化するとこんな感じ。

{
  "single-data": "aaa bbb ccc  ddd\neee\n"
}

> の行よりも多いインデントを付けておいて複数行書いていくと、そのインデント位置を始点に、改行を1スペースとして変換して出力する。それが aaa bbb ccc 部分で分かる。

一方、ddd の行は行頭に2つ多くスペースを置いたので、その2つのスペースが残って ccc ddd (スペース2つ) で残った。そしてその後続の eee については、インデントが戻ったので改行コード \n が入った。

参考文献