FlowingDev

YAMLとは:インデントがスーパーパワーになったワケ

YAMLは、人間が読みやすいデータフォーマットです。シンプルなインデントでデータを構造化するため、設定ファイルやデータ交換の用途で人気があります。

ツールを試す: YAML ビューア

一言で言うと

YAMLは、人間が読みやすいデータシリアライズ言語で、インデントと最小限の句読点を使ってデータ構造を表現します。このおかげで、人間が実際に書いたり読んだりする必要がある設定ファイルで、特に好んで使われています。

YAMLが解決する問題

はじめに、カオスがあった。いや、もっと正確に言うと、XMLのようなフォーマットがありました。もし構造化されたデータ、例えばユーザー設定などを保存したい場合、山括弧の森の中にデータをラップする必要がありました。これはパワフルで、機械には読みやすかったものの、人間がミスなく編集するにはまったくの悪夢でした。

<user>
  <name>Alex</name>
  <roles>
    <role>editor</role>
    <role>admin</role>
  </roles>
  <active>true</active>
</user>

そこにJSON (JavaScript Object Notation) が登場しました。まさに一服の清涼剤!JavaScriptのオブジェクト構文にインスパイアされたJSONは、山括弧を捨て、波括弧、角括弧、コロンを採用しました。より軽量でクリーンになり、あっという間にあらゆるAPIの事実上の標準となったのです。

{
  "name": "Alex",
  "roles": [
    "editor",
    "admin"
  ],
  "active": true
}

しかし、人間が直接いじるとなると、JSONにもクセがあります。たくさんのカンマ、クォート、括弧は、まるで構文の地雷原。カンマを一つ忘れただけで、ファイル全体が無効になります。ある設定がなぜそうなっているのかを説明するコメントを追加したい?残念、JSONはコメントをサポートしていません。

YAMLは、2000年代初頭にこのニッチを埋めるために生まれました。その名前は「YAML Ain't Markup Language」(YAMLはマークアップ言語じゃない)という再帰的な頭字語で、すべてを物語っています。これはドキュメントをマーク付けするシステムではなく、データフォーマットであることに徹底的にこだわっているのです。開発者の主な目標は、人間にとっての読みやすさと書きやすさを最適化することでした。彼らはPythonのクリーンでインデントされた構造を見て、「これをデータにも使えないだろうか?」と考えたのです。その結果、コードというよりは、きれいに整理されたアウトラインのようなフォーマットが生まれました。

内部の仕組み

YAMLの魔法は、そのシンプルさとJSONとの関係性にあります。YAMLパーサーはテキストファイルを読み込み、メモリ内に抽象的なデータ構造を構築します。これはJSONパーサーの動作と非常によく似ています。YAMLとJSONの変換がこれほどシームレスなのは、このためです。これらは同じ基本概念を、ただ違う服を着て表現しているにすぎません。

インデントのゲーム

これこそがYAMLを決定づける特徴です。JSONが {} や [] を使ってネスト(入れ子)を表現するのに対し、YAMLは空白を使います。ルールはシンプル:ある行がその上の行よりも深くインデントされていれば、それはその行の子要素になります。

  • ルール#1: タブではなくスペースを使うこと。アラインメントがぐちゃぐちゃになるのを避けるため、世界はこのルールで合意しています。
  • ルール#2: 一貫性を保つこと。最初のインデントレベルに2つのスペースを使ったなら、すべての最初のレベルで2つのスペースを使いましょう。

違いを見てください。構造は同じですが、YAML版はきれいに整理されたメモのように感じられます。

JSON:

{
  "server": {
    "port": 8080,
    "security": {
      "enable_https": true
    }
  }
}

YAML:

server:
  port: 8080
  security:
    enable_https: true

構成要素: スカラー、シーケンス、マッピング

YAMLのデータは、3つの基本的な要素で構成されています。

  • マッピング (オブジェクト/辞書): キーと値のペアです。YAMLでは key: value のように書きます。コロンの後のスペースは必須ですよ!
    # シンプルなマッピング
    name: "Alex"
    email: alex@example.com
    
  • シーケンス (リスト/配列): 順序付けられたアイテムのリストです。各アイテムをハイフンとスペース (- ) で示します。
    # 役割のシンプルなシーケンス
    - editor
    - admin
    - contributor
    
  • スカラー (値): これが実際のデータです。文字列、数値、真偽値など。YAMLのフレンドリーな特徴の一つは、多くの場合、文字列をクォートで囲む必要がないことです。name: Alex で問題ありません。クォートが必要になるのは、文字列に特殊文字が含まれていたり、他の型(true や 5.0 など)と誤解される可能性がある場合だけです。

これらを組み合わせることで、ほとんどすべてのデータ構造を表現するパワーが得られます。

# ユーザーオブジェクトのリスト
- name: Alex
  email: alex@example.com
  roles:
    - editor
    - admin
- name: Bailey
  email: bailey@example.com
  roles:
    - contributor

上級魔術: アンカー、エイリアス、タグ

YAMLには、JSONにはない隠し玉がいくつかあります。主にファイルをDRY (Don't Repeat Yourself - 同じことを繰り返すな) に保つためのものです。

  • アンカー (&) とエイリアス (*): アンカーを使うと、データの塊に名前を付けることができます。エイリアスを使うと、その塊を別の場所で参照できます。これは、同じブロックを何度も繰り返す必要がある複雑な設定ファイルでは、まさに救世主のような機能です。

    # アンカーでデフォルト設定を定義する
    default_db_config: &db_defaults
      adapter: postgres
      pool: 5
      timeout: 5000
    
    # 異なる環境でエイリアスを使ってデフォルト設定を利用する
    development:
      <<: *db_defaults # << はエイリアスをマージする
      database: myapp_dev
    
    production:
      <<: *db_defaults
      database: myapp_prod
    

    ここで、&db_defaults は再利用可能なテンプレートを作成します。*db_defaults はそれをコピーして取り込みます。もしすべての環境で timeout を変更する必要があるなら、1箇所変更するだけで済みます。

  • タグ (!): タグは、データがどの型であるかをパーサーに明示的に伝える方法です。自分で書くことはめったにありませんが、仕様の一部です。!!str "123" と書くと、パーサーは "123" を数値ではなく文字列として扱うよう強制されます。

実世界でのストーリー

疲れ果てたDevOpsエンジニア

あるチームは、Kubernetes上でアプリケーションインフラを管理していました。すべてのサービス、デプロイメント、設定マップが、それぞれ別の .json ファイルでした。システムが成長するにつれ、「括弧のゲシュタルト崩壊」も深刻化。プルリクエストの差分は、対応の取れない括弧や末尾のカンマの変更で悪夢のようでした。ついに一人のエンジニアがキレて、YAMLへの移行を主導しました。すると突然、deployment.yaml ファイルがスキャン可能になったのです。サービスに特定のメモリ制限がある理由を説明するコメントが追加されました。環境変数のタイポを見つけるのは、構文のパズルではなく、目で見てスキャンするだけの作業になりました。

教訓: 人間が頻繁に読んだり修正したりする、複雑で階層的な設定ファイルにとって、YAMLの読みやすさは生活の質を劇的に向上させます。

静的サイトジェネレータの伝道師

あるコンテンツチームが、会社のブログを管理するために静的サイトジェネレータ(HugoやJekyllなど)を使っていました。各投稿は、タイトル、著者、日付、タグなどのメタデータを記述する「フロントマター」から始まります。当初はJSONのフロントマターを使用していましたが、技術に詳しくないライターたちは、カンマの抜けや不適切なクォートのエスケープに絶えず悩まされていました。ある開発者がフロントマターのフォーマットをYAMLに変更しました。title: My Post、author: Dale といった構文は非常に直感的で、ライターたちからのサポートチケットはゼロになりました。彼らは構文ではなく、執筆に集中できるようになったのです。

教訓: YAMLの構文ノイズの少なさは、構造化データを扱う必要がある非開発者にとって、優れた「インターフェース」となります。

国コードの「落とし穴」

ある開発者が、国際注文を処理するシステムを構築し、2文字の国コードをYAMLの設定ファイルに保存していました。US、DE、JPではすべてうまくいっていました。しかし、ノルウェーからの注文が入ったとき、システムがクラッシュしました。何時間もデバッグした結果、原因が判明しました。YAMLファイルには country: NO と書かれていました。YAMLパーサーは、その有り余る親切心から NO を文字列 "NO" ではなく、ブール値の false と解釈してしまったのです。修正は country: "NO" と簡単でしたが、非常にイライラするものでした。

教訓: YAMLの自動型推論は便利ですが、予期せぬバグにつながることがあります。迷ったときや、ブール値や数値に見えるデータを扱うときは、文字列をクォートで囲みましょう。

よくある間違いと罠

  • タブ vs スペース。 これはYAMLにおける原罪です。インデントには必ずスペースを使わなければなりません。ほとんどのエディタはタブを自動でスペースに変換する設定ができるので、この種の頭痛からあなたを救ってくれるでしょう。
  • ノルウェー問題。 上で見たように、NO, YES, ON, OFF や、一部の数字のようなクォートされていない文字列は、自動的にブール値や数値型に変換される可能性があります。経験則:もしそれが他の何かに見えうる文字列なら、クォートで囲むこと。
  • コロンとスペースを忘れる。 key:value と書くとパースエラーになります。コロンの後にはスペースが必要です: key: value。誰もが少なくとも一度は引っかかる、些細なディテールです。
  • インデントの不一致。 あるネストレベルで2つのスペースを使い、次のレベルで4つ使うと、パーサーは混乱します。インデント幅(2スペースが最も一般的な慣習です)を決めて、それを守りましょう。
  • 複数行文字列の混乱。 YAMLには複数行の文字列を扱うための特殊文字(| と >)があります。| は改行を保持し(コードスニペットに最適)、> は改行を折りたたんで1行にします(長い段落に最適)。間違った方を使うと、テキストがめちゃくちゃになる可能性があります。

なぜ注目すべきか

現代のソフトウェア開発、特にDevOpsやインフラの分野で働いているなら、YAMLから逃れることはできません。

  • 設定こそが王様: Docker Compose、Kubernetes、Ansible、そしてほぼすべてのCI/CDプラットフォーム(GitHub Actions, GitLab CI)は、主要な設定言語としてYAMLを使用しています。これを知っていることはオプションではなく、コアコンピタンスです。
  • 人間中心のデータ: アプリケーション設定からブログ投稿のメタデータまで、人間が直接構造化データを作成したり編集したりする必要があるシステムを作る場合、YAMLは常に最有力候補になるべきです。
  • JSONのスーパーセット: YAMLは(ほとんどの場合)JSONのスーパーセットであるため、明確な移行パスと優れた相互運用性があります。扱いにくいJSONファイルをYAMLに変換して読みやすくし、コメントを追加し、もし他のシステムが純粋なJSONを要求するなら、また元に戻すことができます。

YAMLを、JSONという生で効率的なデータストリームに対する、フレンドリーで整理上手な図書館司書のようなものだと考えてください。あなたのツールキットには両方が必要です。

もっと深く知る

理論はOK。さあ手を動かそう — 100%ブラウザ内で。

ツールを試す: YAML ビューア