FormatArc の YAML 構文チェッカーが行番号つきでエラー表示している画面FormatArc の YAML 構文チェッカーが行番号つきでエラー表示している画面
公開日: 2026-04-13更新日: 2026-06-04

YAML 書き方ガイド|基本ルールとよくある落とし穴

YAML の書き方を基本ルールから実例で解説。インデント崩れ・Norway problem など本番を壊す落とし穴、K8s / GitHub Actions / Docker Compose の実例つき。貼るだけで行番号つきエラー検証も。

TL;DR — 1 分でわかる YAML の書き方

  • インデントはスペースのみ(タブは NG)。2 スペースが事実上の標準。
  • key: value のコロンの後にはスペースが必要。key:value は1つの文字列扱いになる。
  • リストは - (ダッシュ+スペース)、マッピングは key: value
  • 数値・真偽値・日付と誤認されそうな値はクォートする: version: "1.0"
  • エラーを素早く確認したい場合は FormatArc の YAML to JSON 変換ツール に貼り付ければ、行番号付きのエラーメッセージで問題箇所がわかります。

YAML とは、どこで使われているのか

YAML(YAML Ain't Markup Language)は、人間が読みやすいテキスト形式の構造化データフォーマットです。文字列・数値・真偽値・null・リスト・マッピングという、JSON と同じデータモデルを扱えますが、構文は括弧ではなくインデントで階層を表現します。

現代の DevOps やクラウドネイティブのツールを使っていれば、すでに YAML を目にしているはずです。

  • Kubernetes マニフェスト、Helm チャート
  • Docker Compose
  • GitHub Actions、GitLab CI、CircleCI のワークフロー
  • Ansible プレイブック
  • OpenAPI 仕様
  • 静的サイトジェネレーター(Hugo, Jekyll, Eleventy)

この記事では、実際に使う YAML の構文をすべて、具体例と初心者がハマりやすい間違いのリストとともに解説します。YAML と JSON を直接比較したい場合は YAML と JSON の違い、変換手順は YAML を JSON に変換する方法 を参照してください。

YAML を構成する 3 つの要素

YAML ファイルに現れるものは、次の 3 種類のいずれかです。

  • スカラー — 文字列・数値・真偽値・null など、単一の値
  • シーケンス — 順序付きのリスト
  • マッピング — キーと値のペア

これらは自由に入れ子にできます。マッピングがリストを含むことも、リストがマッピングを含むこともできます。これだけで、JSON と互換のある構造ならすべて表現できます。

インデント規則

YAML の階層構造はインデントで表現します。覚えておくべきルールはいくつかあります。

  • スペースのみを使う。タブ文字は多くのパーサーで構文エラー
  • インデント幅を決めたら一貫させる(通常は 2 スペース)
  • 同じ階層の要素は同じインデントにそろえる
  • 構造は閉じ括弧ではなくインデントで決まる

シンプルな有効例です。

database:
  host: localhost
  port: 5432
  credentials:
    user: admin
    password: secret

database はマッピングで、hostportcredentials を含みます。credentials はさらに入れ子のマッピングです。2 スペースのインデントで構造がひと目でわかります。

キーバリュー(マッピング)の書き方

マッピングは key: value の形式で書きます。コロンの後には半角スペースが必要です。key:value と書くと 1 つの文字列として扱われ、マッピングにはなりません。

name: Alice
age: 30
is_admin: true
bio: null

キーは通常は単純な文字列ですが、クォートすればスペースを含めることもできます。

"full name": Alice Cooper

値にはスカラー・シーケンス・マッピングなど YAML のどの型でも置けます。

リスト(シーケンス)の書き方

シーケンスは行頭に - (ハイフン+半角スペース)を置きます。

fruits:
  - apple
  - banana
  - cherry

リストには入れ子のマッピングも入れられます。

users:
  - name: Alice
    role: admin
  - name: Bob
    role: editor

ハイフンが新しいリスト項目の開始を示し、次のハイフンまでの内容がその項目に属します。

JSON に近いインライン(フロー)記法もあります。

fruits: [apple, banana, cherry]
users: [{name: Alice, role: admin}, {name: Bob, role: editor}]

フロー形式は短いリストでは便利ですが、データが大きくなると読みにくくなります。現実のファイルではブロック形式を使うのが無難です。

文字列とクォート

YAML の文字列はほとんどの場合クォートなしで書けます。

greeting: Hello, world

クォートが必要なのは次のようなケースです。

  • 別の型として解釈されてしまう場合: version: "1.0"country: "NO"postal_code: "07030"
  • 値が -:[{|>*&!%@ のような特殊文字で始まる
  • 値にコロン+スペースが含まれる(マッピングと誤認されるため)
  • \n\t のようなエスケープシーケンスを使いたい

シングルクォートとダブルクォートの両方が使えます。ダブルクォートはエスケープを解釈し、シングルクォートはそのまま文字として扱います。

escaped: "line1\nline2"
literal: 'line1\nline2'

マルチライン文字列

長いテキストには二つの書き方があります。

リテラルブロック | は改行をそのまま保持します。

description: |
  これが 1 行目です。
  これが 2 行目です。

  空行の後の 4 行目です。

フォールドスカラー > は改行を空白に畳み込むので、ソース中で折り返した長文を 1 行にまとめるのに便利です。

paragraph: >
  この長い文章はソース中で複数行に
  分けて書かれていますが、YAML は
  これを 1 行に畳み込みます。

Chomp 指示子: 末尾改行を strip / clip / keep

YAML のブロックスカラーには「末尾の改行をどう扱うか」を決める chomp 指示子があります。指示子は | または > の直後に書きます。

指示子 挙動
(なし) — clip 末尾改行を 1 つ残す。デフォルト。 |
- — strip 末尾の改行をすべて削る。 |- >-
+ — keep 末尾の空行をすべて残す。 |+ >+
clip: |
  line one
  line two
strip: |-
  line one
  line two
keep: |+
  line one
  line two

折り畳み形式(>>->+)にも同じ 3 モードが適用されます。|- は YAML を JSON や環境変数に埋め込む際、末尾改行が邪魔になる場面で使います。|+ はシェルスクリプトを生成するときなど、末尾の空行に意味がある場面で使います。

型とパーサの型推論

YAML はクォートなしの値から型を推論します。同じリテラルでも、パーサが実装している YAML のバージョンや使っているスキーマ次第で、整数・浮動小数点数・日付・文字列のいずれにもなります。

integer: 42
hex: 0xFF              # 255 (integer, hex)
octal: 0o17            # 15 (integer, octal, YAML 1.2)
octal_legacy: 0644     # 420 (integer, octal, YAML 1.1) — file mode trap
float: 3.14
negative: -7
exponential: 1e3       # 1000.0 (float, scientific notation)
infinity: .inf         # +Infinity (float)
negative_infinity: -.inf
not_a_number: .nan     # NaN (float)
boolean_true: true
boolean_false: false
null_value: null
tilde_null: ~
date: 2026-04-13
timestamp: 2026-04-13T09:30:00Z

これらはいずれもクォートすれば文字列として固定できます。

version_string: "1.0"    # not the number 1.0
zip_code: "07030"        # not the number 7030
file_mode: "0644"        # string, not octal integer

次の表は、クォートなしのリテラルが、現代的な YAML 1.2 Core スキーマのローダー(PyYAML、js-yaml、SnakeYAML のデフォルト)と、YAML 1.1 のローダー(古い PyYAML、Symfony YAML)でそれぞれ何になるかをまとめたものです。意外な挙動のほとんどは、この 2 列の差に潜んでいます。

リテラル YAML 1.2 Core YAML 1.1 注意点
42 integer (42) integer (42)
0xFF integer (255) integer (255) 16 進パースは意図的な仕様
0o17 integer (15) (認識されない) YAML 1.2 のみ
0644 integer (644) integer (420, 8 進) ファイルモードがバージョンで変わる
1e3 float (1000.0) float (1000.0) 一部ツールは表示で .0 を落とす
.inf / -.inf float (±Infinity) float (±Infinity) JSON にシリアライズ不可
.nan float (NaN) float (NaN) JSON にシリアライズ不可
2026-04-13 string date (日付オブジェクト) JSON ↔ YAML の往復で型が変わる
2026-04-13T09:30Z string timestamp 同じ問題
true / false boolean boolean
yes / no / on / off string boolean 「Norway problem」
NO string boolean (false) 次節で扱う
~ / null / Null / NULL null null どの大文字小文字でも null
1.0 float (1.0) float (1.0) 一部ツールは 1 として再シリアライズ

パーサが少しでも本番に近いなら、いちばん右の列にあるものはすべて潜在的なバグとして扱ってください。手元のローダーがどのバージョンを使っているかを知る最速の方法は、代表的なファイルを FormatArc の YAML to JSON 変換ツール に貼り付けて JSON 出力を確認することです。"NO"false か、"2026-04-13" か ISO の日付文字列か、といった具合に判別できます。

この 2 列の差が生まれるのは、YAML 1.1 と YAML 1.2 で型推論の定義が異なるためです。YAML 1.1 は、タイムスタンプ・60 進数(base-60)・Norway problem を引き起こす幅広い真偽値の語彙を含む、広範な暗黙の型タグを抱えていました。YAML 1.2 はそれを、より狭い Core スキーマ に置き換えました。Core スキーマは真偽値を truefalse に限定し(仕様の Core 正規表現は先頭大文字や全大文字の True/TRUE/False/FALSE も受理しますが、yes/no/on/off はもう受理しません)、暗黙のタイムスタンプおよび 60 進数タグを廃止し、それ以外は JSON の値型を踏襲します。リテラルが整数・浮動小数点数・真偽値・null のどれになるかを決める正規表現の完全なセットは YAML 1.2.2 仕様 に公開されています。2 つのツールがクォートなしの値の意味で食い違うとき、その違いはほぼ必ず、一方が 1.1 の型ルールを、もう一方が 1.2 の Core スキーマを実装していることに行き着きます。

Norway problem — NOfalse に化ける罠

YAML でもっとも有名な落とし穴が「Norway problem」です。YAML 1.1 のパーサ(PyYAML、Symfony YAML、古い SnakeYAML など、いまだに広く使われています)はクォートなしの NO を真偽値 false として解釈します。次のような国コードのリストは:

countries:
  - DE
  - FR
  - NO
  - SE

パースされた瞬間に ["DE", "FR", false, "SE"] になってしまいます。YESONOFFYN、さらに大文字小文字違いまでパーサ次第で同じ罠を踏みます。

回避策は誤解されうる値をクォートすることです:

countries:
  - "DE"
  - "FR"
  - "NO"
  - "SE"

YAML 1.2 では true / false のみに絞られましたが、本番ツールの多くはいまだに 1.1 系のローダーを同梱しています。国コード・言語コード・バージョン文字列・短い識別子などはすべてクォートしておくのが安全です。パーサを問わない設定を維持したい場合は FormatArc の YAML to JSON 変換ツール に貼り付ければ、出力された JSON で "NO" が文字列のまま残っているか即座に確認できます。

具体的なルールは公式仕様で定義されています。今日の厳密な真偽値集合を定めるのが YAML 1.2.2 仕様、レガシーツールが現在もそのまま実装しているのが YAML 1.1 仕様 です。手元のローダーがどちらに準拠しているかを把握しておくと、NO が文字列として残るか false になるかを判断できます。

コメント

コメントは # から行末までです。単独の行にも、値の後ろにも書けます。

# 上流リクエストの最大リトライ回数
retries: 3  # これ以上は上流のタイムアウトを超えてしまう

コメントは設定ファイルにおける YAML の最大の強みのひとつです。「何をしているか」ではなく「なぜこの値なのか」を説明するのに使ってください。JSON に変換するとすべて消えるので、YAML を一次ソースとして保管するのが安全です。JSON でどうしてもコメントを書きたい場合は JSON にコメントを書く方法 で JSONC / JSON5 の回避策を解説しています。

アンカーとエイリアスで再利用する

YAML は & でアンカーを打ち、* でエイリアスを参照できます。<<: のマージキーでマッピングをデフォルト値として取り込めます。

defaults: &defaults
  adapter: postgres
  host: db.internal
  pool: 5

development:
  <<: *defaults
  database: myapp_dev

production:
  <<: *defaults
  database: myapp_prod
  pool: 20

productiondefaults を引き継ぎつつ pool を上書きしています。環境ごとの設定をコピペせずに共通化できる、きれいな書き方です。

マージキー(<<:)で設定を共有する

<<: のマージキーはアンカーともっとも相性のよい機能です。あるマッピングのキーを別のマッピングに取り込めるので、「同じだけどここだけ上書き」を繰り返さずに表現できます。Docker Compose、GitLab CI、Rails の database.yml など、設定ファイルの実例で頻出します。

base: &base
  image: node:20
  restart: unless-stopped
  environment:
    NODE_ENV: production

services:
  api:
    <<: *base
    command: npm run start:api
  worker:
    <<: *base
    command: npm run start:worker
    environment:
      NODE_ENV: production
      WORKER_QUEUE: high

注意点が 2 つあります。

  • マージキーは 1 階層だけしか合成しません。ネストしたマッピング(上の例の environment など)は深くマージされず、丸ごと上書きされます。
  • マージキーは YAML 1.1 の機能です。厳密な YAML 1.2 パーサは無視することがありますが、Docker Compose や GitLab はいまだに 1.1 セマンティクスをサポートしているため使えます。

スキーマとタグ: YAML はどう型を決めるのか

YAML 1.2 は、クォートなしのリテラルの解釈方法を制御する 3 つのスキーマを定義しています。

  • FailSafe — 文字列・マッピング・シーケンスのみ。もっとも安全なスキーマで、それ以外はすべて文字列になります。デフォルトになることはほとんどありません。
  • JSON — JSON 互換の型(文字列・整数・浮動小数点数・真偽値・null・マッピング・シーケンス)。JSON.parse が生成するものと一致します。
  • Core — 一般的なデフォルト。上の表の型推論ルール(hex・octal・.inf.nan~)を追加します。

ほとんどのパーサは Core を同梱します(PyYAML の safe_load、js-yaml のデフォルト、SnakeYAML の SafeConstructor)。Symfony YAML はいまだに YAML 1.1 セマンティクスをデフォルトにしています。手元のローダーがどのスキーマを使うかを知れば、型の表のどの行が適用されるかがわかります。

スキーマが取り違える場合 — 文字列にしたかったのに version: 1.0 が浮動小数点数としてパースされるなど — は、明示的なタグで上書きします。

version: !!str 1.0       # forces string "1.0"
count: !!int "42"        # forces integer 42 even though it is quoted
empty: !!null ""         # explicit null instead of empty string

!! プレフィックスは「デフォルトのタグライブラリのタグを使う」という意味です。カスタムタグは単一の ! を使い(たとえば CloudFormation テンプレートの !Ref)、パーサ側がそれを理解している必要があります。アプリケーションレベルの YAML ファイルのほとんどは、型の罠を解除するために !!str だけあれば十分です。

マルチドキュメント

1 つの YAML ファイルに複数のドキュメントを入れることができます。区切りは --- の行です。

---
kind: Service
name: web
---
kind: Deployment
name: web
replicas: 3

Kubernetes で複数マニフェストを 1 ファイルにまとめるときに使う形式です。JSON にはこれに相当する仕組みがないため、変換時はどちらか一方を選ぶか、外側を配列でラップする必要があります。

実際に YAML を書く 3 つの場面

数行の設定ファイルでも本番マニフェストでも、適用される文法は同じです。2026 年の開発で YAML に出会う典型的な 3 つの場面を紹介します。

Kubernetes Deployment マニフェスト

最小構成の Deployment でも、マッピング・シーケンス・マルチライン文字列・Norway problem 系のブール値がすべて登場します。spec.template.spec.containers あたりのインデントずれが失敗の典型です。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27-alpine
          ports:
            - containerPort: 80
          env:
            - name: FEATURE_FLAG_NEW_HEADER
              value: "true"      # 意図的にクォート — 裸の true はブール扱い
          resources:
            limits:
              cpu: "500m"
              memory: 256Mi

value: "true" をクォートしているのが要点です。クォートを外すと Kubernetes はブール値として受理し、コンテナには言語次第で True(Python 風)が渡るか起動失敗します。具体的な失敗パターンは次節で扱います。

GitHub Actions ワークフロー

GitHub Actions のワークフローはマッピングが深くネストし、run ブロックでマルチライン文字列が頻出します。|(リテラル)と >(フォールド)の使い分けが効いてくる場面です。

name: CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "20"      # 末尾 0 を保つためクォート
      - name: Install
        run: npm ci
      - name: Test
        run: |
          npm run lint
          npm run build
          npm test -- --run

ここでもっとも多い破壊は node-version: "20" のクォートを外してしまうことです。YAML が整数 20 に強制変換するため、setup-node のバージョンによっては受理されません。「数字に見えるが文字列でなければならない」値はすべてクォートしてください。

Docker Compose のサービス定義

Compose ファイルはマッピング・シーケンス・環境変数辞書・バインドマウント文字列が混在する短い YAML です。インデント問題の練習にちょうどよい長さです。

services:
  web:
    image: nginx:1.27-alpine
    ports:
      - "8080:80"               # 60 進数として解釈されないようクォート
    environment:
      NGINX_HOST: example.com
      NGINX_PORT: "80"          # クォート必須: 環境変数値は文字列
    volumes:
      - ./html:/usr/share/nginx/html:ro
    depends_on:
      - api
  api:
    build: ./api
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 5s
      retries: 3

落とし穴は 2 つ。"8080:80" のクォートを外すと YAML 1.1 系パーサが 60 進数として読みうる点と、environment: 配下は最終的に文字列として渡されるため値はクォートしておく方が安全である点です。次節で具体的な失敗例を見ていきます。

よくある間違いと見つけ方

多くの開発者が一度はハマる YAML の落とし穴です。

  • タブ文字でインデントしている — 見えないタブが混入すると分かりにくいエラーになる
  • コロンの後にスペースがない — key:value は 1 つの文字列として扱われる
  • インデントがそろっていない — 同じ階層の要素は同じ幅でそろえる必要がある
  • クォートなしの NOOFFYESON が真偽値になる(ノルウェー問題)
  • クォートなしの値にコロンが含まれる — time: 10:30 が 60 進数として解釈されることがある
  • ブロック形式とフロー形式の混在でパーサーが混乱する
  • 同じマッピング内で重複キーを使う — 実装依存の挙動になる

こうした間違いを一番早く見つける方法は、パーサーに読ませることです。インストール不要で試すなら、FormatArc の YAML to JSON 変換ツール に貼り付けるだけでチェックできます。正しい YAML なら JSON が即座に表示され、間違っていれば行番号付きのエラーメッセージで問題箇所を指してくれます。

FormatArc でブラウザ内 YAML バリデーション

FormatArc のブラウザ完結ツールは簡易 YAML リンターとしても使えます。

YAML to JSON の変換結果、行番号付きで構文チェックが通った画面YAML to JSON の変換結果、行番号付きで構文チェックが通った画面

  • YAML to JSON — YAML を貼り付けて JSON を得る。エラー時は行番号付きで表示
  • JSON to YAML — JSON から出発して YAML の形を学びたいときに
  • JSON Formatter — 変換結果の JSON を整形・エラー表示する

すべてブラウザで完結します。内部の設定ファイルやシークレットをデバッグ中に貼り付けても、データは手元から出ません。

よくある質問

YAML のインデントにタブを使えますか?

使えません。YAML 仕様はスペースのみを許容しており、タブ文字は多くのパーサーで構文エラーになります。.yml.yaml の編集時は Tab キーで 2 スペースが入るようにエディタを設定してください。

.yml.yaml の違いは?

違いはありません。どちらの拡張子も YAML パーサーはまったく同じように扱います。公式仕様では .yaml を推奨していますが、.yml も広く使われていて問題ありません。

文字列は必ずクォートすべきですか?

いいえ、基本的にはクォートなしで書けます。クォートが必要なのは、別の型として解釈されてしまう値や、特殊文字 -:[{|> で始まる値です。

version: 1.0 と書いたのに 1 になってしまうのはなぜですか?

YAML は 1.0 を浮動小数点数としてパースし、一部のツールはそれを 1 としてシリアライズし直します。文字列として保持したい場合は version: "1.0" のようにクォートしてください。

インデントのスペース数はいくつが正解ですか?

2 スペースが慣習です。Kubernetes、Docker Compose、GitHub Actions など、ほとんどの例が 2 スペースを使っています。4 スペースでも動きますが、1 つのファイル内では必ず統一してください。

インストールせずに YAML を検証する方法は?

FormatArc の YAML to JSON 変換ツール に貼り付けるだけで検証できます。有効な YAML なら即座に JSON が出力され、無効なら行番号付きのエラーメッセージが表示されます。

1 つのファイルに複数の YAML ドキュメントを入れられますか?

入れられます。区切りは --- だけの行です。Kubernetes でマニフェストをまとめるときの標準的な形式です。1 ファイルにいくつでもドキュメントを並べられます。

関連記事

まとめ

  • YAML は括弧ではなくインデントで構造を表現します
  • インデントはスペースのみで、一貫させることが重要です
  • 文字列は誤解釈されるときだけクォートします
  • コメント・マルチライン・アンカーで設定ファイルを読みやすくできます
  • 構文の検証は FormatArc の YAML to JSON ツール に貼り付けるのが最速です