YAML

YAMLとは

YAML は、設定やデータを人間が読み書きしやすい形で書くためのテキスト形式です。名前は "YAML Ain't Markup Language" の再帰的な略で、「文書を飾るための言語ではなく、データそのものを表す形式」という立場を示しています。ファイルの拡張子は .yaml.yml の両方が使われます。

id: 42
name: 山田太郎
tags:
  - frontend
  - backend
active: true

同じ内容を [[JSON]] で書くと、波括弧・ダブルクォート・カンマが必要になります。YAML は記号を減らし、インデントの深さで構造を表すことで、人が直接編集する設定ファイルとして読みやすくしています。

初学者向けポイント

  • 構成要素は3つだけ: スカラー(単一の値)・リスト(順序のある並び)・マップ(キーと値の対応)
  • インデントは半角スペースのみで、タブは使えない
  • # から行末までがコメント。JSON と違いコメントを書ける。ただしコメントとして扱われるのは行頭か空白の直後にある # だけで、url: http://example.com#frag# は値の一部になる

3つの基本要素

スカラー

文字列・数値・真偽値・null が該当します。文字列はクォート無しで書けますが、必要なときだけ囲みます。

port: 8080 # 数値
debug: true # 真偽値
memo: # 値を省略すると null
zip: "0120" # クォートで囲むと文字列。先頭のゼロも消えない

リスト

行頭に - を置いて並べます。角括弧を使って1行で書く記法もあります。

ports:
  - 80
  - 443
hosts: [web01, web02]

マップ

キー: 値 の並びです。値の位置にリストやマップを置けば、いくらでも入れ子にできます。

server:
  host: example.com
  ports:
    - 80
    - 443

JSONとの関係

YAML 1.2 の仕様上、JSON は YAML の部分集合です。つまり正しい JSON はそのまま YAML としても読めます。YAML は JSON の上位互換であり、両者は対立する形式ではありません。

{ "id": 42, "name": "山田太郎" } # JSON のまま書いても YAML として有効

使い分けの目安は次のとおりです。

観点JSONYAML
主な用途プログラム間のデータ交換人が手で編集する設定ファイル
コメント書けない# で書ける
記号の量多い少ない
解釈の曖昧さほぼ無い型の自動推論で起きやすい

API のレスポンスを YAML で返すことはほとんどありません。パースが重く、空白の違いだけで壊れるためです。機械がやり取りするなら JSON、人が書くなら YAML と覚えておけば実務では困りません。

実務でつまずくところ

タブでインデントできない

YAML はタブ文字をインデントとして認めません。エディタの設定でタブが混ざると、found character that cannot start any token のような分かりにくいエラーになります。YAML を書くファイルは「インデントは半角スペース2つ」に設定しておくのが最初の防御策です。

yes / no が真偽値になる

広く使われている YAML 1.1 系のパーサーでは、yesnoonoff も真偽値として解釈されます。有名なのがノルウェーの国コード NOfalse になってしまう例で、"Norway problem" と呼ばれます。

countries:
  - NO # false と解釈されうる
  - "NO" # 文字列として安全

同じ理由で、version: 1.10 は数値として 1.1 に丸められ、time: 12:30 は 750 という数値に解釈されることがあります。文字列として扱ってほしい値はクォートで囲むのが確実です。バージョン番号・国コード・時刻・先頭にゼロが付く数字は特に注意します。

インデントが崩れても壊れない

YAML の事故で一番多いのは、エラーにならず構造だけが静かに変わるケースです。

# 意図: server の下に port がある
server:
  host: example.com
  port: 8080

# インデントを1段浅くすると port はトップレベルの別項目になる
server:
  host: example.com
port: 8080

前者は server.port、後者はトップレベルの port です。どちらも YAML としては正しいため、アプリを起動して「設定が効いていない」と気づくまで発覚しません。差分レビューでは行の中身だけでなく、インデントの深さを必ず確認します。

アンカーとエイリアスで重複を減らす

同じ内容を何度も書くとき、&名前 で印を付けておき(アンカー)、*名前 で参照できます(エイリアス)。<<: を使うとマップの中身を取り込めます。

defaults: &defaults
  image: node:20
  timeout: 300

test:
  <<: *defaults
  command: npm test

build:
  <<: *defaults
  timeout: 600 # 個別に上書き

重複が消える一方で、参照が増えるほど最終的にどの値が使われるのかを目で追えなくなります。数か所の共通化にとどめ、深い入れ子にはしないのが無難です。

なお、外部から受け取った YAML をそのまま読み込むと、パーサーによっては任意のオブジェクトが生成されてしまいます。信頼できない入力には、Python の yaml.safe_load のような安全な読み込み関数を使います。

どこで使われるか

場面
CI設定GitHub Actions の .github/workflows/*.yml([[CI/CD]])
コンテナ構成Docker Compose の compose.yaml([[Docker]])
コンテナ運用[[Kubernetes]] のマニフェスト(Deployment・Service など)
構成管理[[Ansibleと構成管理]] の Playbook
記事・ドキュメントMarkdown 先頭の frontmatter

共通しているのは「人が手で書き、機械が読む」という位置づけです。これらの設定ファイルは実行環境そのものを決めるため、アプリのコードと同じようにバージョン管理し、レビューを通してから反映します。

関連技術とのつながり

  • [[JSON]] — 対になるデータ形式。JSON は YAML の部分集合で、機械同士のやり取りではこちらが標準
  • [[CI/CD]] — パイプラインの定義を YAML で書く。設定ミスがそのままビルド失敗になる
  • [[Kubernetes]] — マニフェストは YAML。あるべき状態を宣言的に記述する代表例
  • [[Ansibleと構成管理]] — Playbook を YAML で書き、サーバー設定を自動化する
  • [[Docker]] — Docker Compose が複数コンテナの構成を YAML で受け取る
  • [[IaC]] — インフラを設定ファイルとして扱う考え方。その記述形式として YAML が多用される
Q: YAMLのインデントについて正しいのはどれ?
- [x] 半角スペースを使う。タブ文字はインデントとして使えない
- [ ] タブ文字を使う。半角スペースは使えない
- [ ] タブと半角スペースを自由に混ぜてよい
解説: YAMLはタブをインデントとして認めません。混入すると分かりにくいエラーになるため、エディタ側でスペース2つに設定しておくのが定石です。

Q: 国コードの `NO` をYAMLに書くとき、文字列として安全に扱う方法はどれ?
- [x] `"NO"` のようにクォートで囲む
- [ ] そのまま `NO` と書く
- [ ] 先頭に `#` を付ける
解説: YAML 1.1系では yes/no/on/off も真偽値として解釈され、`NO` は false になりえます("Norway problem")。文字列として扱ってほしい値はクォートで囲みます。

Q: YAMLとJSONの関係として正しいのはどれ?
- [x] JSONはYAMLの部分集合で、正しいJSONはYAMLとしても読める
- [ ] YAMLとJSONは互いにまったく変換できない別系統の形式
- [ ] YAMLはJSONと違ってコメントを書けない
解説: YAML 1.2の仕様上、JSONはYAMLの部分集合です。YAMLはコメントを書けるため、人が編集する設定ファイル向きです。