YAMLとは?JSONとの違いと設定ファイルでの落とし穴
クラウドサービスやCI/CDの設定ファイルを開くと、たいていこの形式に出会います。
version: "3"
services:
web:
image: nginx
ports:
- "80:80"
これがYAML(ヤムル)です。Docker Compose、Kubernetes、GitHub Actions、Ansible——設定ファイルの標準的な形式として、あちこちで使われています。
そして、こういう疑問が出てきます。
JSONとは何が違うのか。なぜ2つあるのか。
実は両者には、はっきりした関係があります。
「Its primary focus was making YAML a strict superset of JSON.」
(YAML 1.2仕様の主眼は、YAMLをJSONの厳密なスーパーセットにすることだった)
——YAML 1.2.2 仕様
YAML 1.2は、JSONを内包しています。つまり正しいJSONは、そのまま正しいYAMLでもあります。
この記事では両者の違いと、YAML特有の落とし穴を整理します。JSONそのものについては JSONとは?データ形式の基本とAPIでの使われ方 をご覧ください。
同じデータを書き比べる
まず見た目の違いから。同じ内容をJSONとYAMLで書くと、こうなります。
JSON
{
"name": "web-server",
"port": 8080,
"enabled": true,
"tags": ["production", "tokyo"]
}
YAML
name: web-server
port: 8080
enabled: true
tags:
- production
- tokyo
YAMLでは波かっこ、角かっこ、引用符、カンマがほぼ消えます。代わりにインデント(字下げ)が階層構造を表します。
YAMLとJSONの違い
| JSON | YAML | |
|---|---|---|
| 階層の表し方 | 波かっこ {} |
インデント |
| コメント | 書けない | 書ける(#) |
| 主な用途 | プログラム間のデータ交換(API) | 人が書く設定ファイル |
| 読みやすさ | 機械向き | 人間向き |
| 厳密さ | 曖昧さが少ない | 解釈の余地がある |
決定的な差は「コメント」
JSONにはコメントを書く構文がありません。これは設定ファイルとしては大きな制約です。
「この設定はなぜこの値なのか」「一時的に無効化している」といった情報を残せないためです。YAMLなら # で書けます。
# 本番環境では 8080 を使う(80はロードバランサが使用)
port: 8080
設定ファイルにYAMLが選ばれる最大の理由が、これです。
【最重要】YAMLの落とし穴
YAMLは人間に読みやすい代わりに、「書いたつもりと違う値になる」ことがあります。
① 国コード「NO」が false になる
有名な例がこれです。
countries:
- JP
- US
- NO # ← ノルウェー
YAML 1.1では、この NO が文字列ではなく「false」として解釈されます。
原因は仕様にあります。YAML 1.1のboolean型は、次の値をすべて真偽値として扱うと定義されています。
y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF
——YAML 1.1「Boolean Language-Independent Type」
y、n、yes、no、on、off がすべて真偽値になります。
そのため次のような事故が起こります。
| 書いた内容 | 意図 | YAML 1.1での解釈 |
|---|---|---|
country: NO |
ノルウェー | false |
answer: yes |
文字列 “yes” | true |
switch: on |
文字列 “on” | true |
YAML 1.2では改善されている
この問題は仕様側で対処されました。
「It also removed many of the problematic implicit typing recommendations.」
(YAML 1.2は、問題のある暗黙型付けの推奨を多く削除した)
YAML 1.2ではtrue / false(True、TRUEを含む)だけが真偽値として扱われ、y、yes、on とその否定形は文字列になります。
ただし、実装が1.2とは限らない
ここが実務上の注意点です。仕様が改訂されても、使っているツールやライブラリが1.1準拠のままというケースがあります。
確実な対処はひとつです。
country: "NO" # ← 引用符で囲む
文字列として扱ってほしい値は、引用符で囲む。これを習慣にすれば、どちらの仕様でも安全です。
② 先頭ゼロが消える・8進数になる
zip: 01234
郵便番号や電話番号のつもりでも、数値として解釈されます。先頭のゼロが失われたり、処理系によっては8進数と見なされたりします。
これも引用符で解決します。
zip: "01234"
③ タブ文字が使えない
YAMLのインデントは半角スペースのみです。タブ文字を使うとエラーになります。
エディタが自動でタブを挿入する設定になっていると、見た目では気づけません。YAMLを編集するときは、タブをスペースに変換する設定にしておいてください。
④ インデントのずれが構造を変える
server:
host: example.com
port: 8080 # ← スペース1個多い
JSONなら波かっこの対応が崩れてエラーになりますが、YAMLは空白の数で構造が決まるため、意図しない階層になったりエラーになったりします。
JSONにはないYAMLの機能
コメント以外にも、YAMLには設定ファイル向けの機能があります。
複数行の文字列
スクリプトや長い説明文を、そのままの改行で書けます。
script: |
echo "line 1"
echo "line 2"
| は改行をそのまま保持し、> は改行を空白に畳んで1行にします。JSONでは n をエスケープして1行に書くしかないため、可読性が大きく違います。
アンカーとエイリアス(使い回し)
同じ設定を複数箇所で使うとき、定義を1か所にまとめられます。
defaults: &defaults
region: ap-northeast-1
retries: 3
production:
<<: *defaults
instances: 10
& で名前を付け(アンカー)、* で参照します(エイリアス)。設定の重複を減らせる反面、追いにくくなるため、使いすぎには注意してください。
結局、どちらを使うべきか
| 場面 | 適した形式 | 理由 |
|---|---|---|
| APIのやり取り | JSON | 曖昧さが少なく、ほぼすべての言語が標準対応 |
| 人が編集する設定ファイル | YAML | コメントが書け、記号が少なく読みやすい |
| ログ・データ保存 | JSON | 1行1レコードで扱いやすい |
| 機械が自動生成する | JSON | 整形の揺れが起きない |
「人が書くか、機械が書くか」で分かれると考えると分かりやすくなります。
APIのレスポンスがJSONなのは、機械同士のやり取りで解釈が揺れては困るからです(REST APIとは?6つの原則・HTTPメソッド・設計の考え方)。
非エンジニアが知っておくべきこと
設定ファイルを直接編集する機会は、情報システム担当でなくても増えています。SaaSの一括設定、CI/CDの調整、クラウドの構成管理——いずれもYAMLで書かれていることが多いためです。
最低限、次の3つを押さえておけば事故を防げます。
- インデントは半角スペース。タブは使わない
- 文字列として扱いたい値は引用符で囲む(特に
NO、yes、on、先頭ゼロの数字) - コピペしたら必ず検証する(多くのエディタにYAMLの構文チェック機能がある)
また、YAMLは設定ファイルという性質上、機密情報が書かれやすい形式でもあります。APIキーやパスワードを直接書き込んだまま共有リポジトリに置いてしまう事故は珍しくありません。そうした値は環境変数やシークレット管理の仕組みに分離してください。
よくある質問
Q. YAMLは何の略ですか?
「YAML Ain’t Markup Language」の略です。自身を再帰的に参照する、開発者らしい命名になっています。
当初は「Yet Another Markup Language」でしたが、マークアップ言語ではなくデータ表現のための形式であることを明確にするため、現在の名称になりました。
Q. JSONをYAMLに変換できますか?
YAML 1.2はJSONのスーパーセットなので、正しいJSONはそのまま正しいYAMLとして扱えます。変換ツールも多数あります。
逆にYAMLからJSONへの変換は、YAML固有の機能(コメント、アンカーなど)が失われる点に注意してください。コメントは変換すると消えます。
Q. 拡張子は .yml と .yaml のどちらですか?
どちらも使われています。公式には .yaml が推奨されていますが、実際には .yml も広く使われており、ツールによって既定が異なります。
Docker Compose や GitHub Actions は .yml、Kubernetes では .yaml をよく見かけます。ツールのドキュメントに従うのが確実です。
Q. インデントは何文字が正しいですか?
仕様上の決まりはありませんが、2スペースが慣習です。重要なのは文字数よりファイル内で統一されていることです。
Q. エラーの原因が分かりません
YAMLのエラーはインデント・タブ・引用符のいずれかであることがほとんどです。
エディタの構文チェック機能や、オンラインのYAMLバリデータで確認してください。目視だけでスペースの数を追うのは非効率です。
参考にした主な調査・資料
- YAML Ain’t Markup Language (YAML™) revision 1.2.2|YAML公式仕様
- Boolean Language-Independent Type for YAML™ Version 1.1|YAML公式
- RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format|IETF
※仕様の引用は原文(英語)からの抜粋で、和訳は本記事によるものです。実際の挙動は使用するライブラリやツールのバージョンによって異なる場合があります。
まとめ
- YAML 1.2はJSONの厳密なスーパーセット。正しいJSONはそのまま正しいYAML
- 違いはインデントで階層を表すこととコメントが書けること
- 設定ファイルにYAMLが選ばれる最大の理由はコメントが書けるから
- YAML 1.1では NO・yes・on などが真偽値になる(ノルウェーの国コード問題)
- YAML 1.2で改善されたが、実装が1.1準拠のことがある
- 文字列として扱いたい値は引用符で囲む——これが確実な対処
- インデントは半角スペースのみ。タブは使えない
- 使い分けは「人が書くならYAML、機械が書くならJSON」
YAMLは読みやすい形式ですが、読みやすさと引き換えに、解釈の余地を持っています。
引用符をひとつ足すかどうかで結果が変わる——それを知っているだけで、防げる事故があります。