記事一覧へ戻る
フォーマット比較

YAML vs JSON vs TOML — 設定ファイルのフォーマットをどう選ぶか

アプリの設定 / CI/CD / インフラ定義で YAML / JSON / TOML をどう使い分けるかを、可読性 / 表現力 / パースの厳密さ / ツール対応 で比較。YAML の罠 (Norway 問題など) も整理します。

どの軸で選ぶか — 4 つの判断基準

設定フォーマット選びは「結局どれが読みやすいか」だけでは決められません。判断の基準は 4 つです。可読性 はチームの誰がいつ編集するか (アプリ開発者か / SRE か / 非エンジニアか) で変わります。表現力 はネスト・配列・コメント・複数行文字列など、設定で表現したい構造をそのまま書けるかどうか。パースの厳密さ は「意図しない型変換」「末尾カンマの可否」「空白の有意性」など、人間が踏みやすい罠の少なさを左右します。ツール・エコシステム対応 は使う側のランタイム (Kubernetes / Rust Cargo / Node.js / Python) がどれを第一級で受け取るかで実質的に決まります。

「YAML は読みやすい」「JSON は厳密」「TOML はモダン」のような一面的な評価ではなく、4 軸のどれが致命的かで答えが変わります。Kubernetes マニフェストなら表現力と既存エコシステム、API レスポンスなら厳密さと相互運用、Cargo パッケージ宣言なら可読性とエコシステム、という具合に。

3 フォーマットの比較表

項目YAMLJSONTOML
標準仕様YAML 1.2 (2009)RFC 8259 (2017)TOML 1.0.0 (2021)
開発年200120012013
コメント可 (#)不可可 (#)
末尾カンマ該当なし不可配列のみ可
ネスト記法インデント有意中括弧テーブル [a.b.c]
配列- または [...][...][...]
複数行文字列` >` で可不可 (\n で表現)
型推論暗黙 (罠あり)明示明示 (日付型まで含む)
主要採用例Kubernetes / GitHub Actions / Docker ComposeWeb API / package.json / VS CodeCargo.toml / pyproject.toml / Hugo
ファイル拡張子.yaml .yml.json.toml

YAML の最大の罠は Norway 問題 と呼ばれる暗黙の真偽値変換です。YAML 1.1 では NO / yes / on / off が自動的に真偽値に変換されるため、国コード "NO" (ノルウェー) を引用符なしで書くと false になります。YAML 1.2 で挙動は厳格化されましたが、PyYAML をはじめ多くのパーサが 1.1 互換モードを既定にしているため、いまも実害があります。インデントずれ (タブとスペースの混在、項目間のインデント不一致) も頻発します。

JSON は規格が短く挙動が予測しやすい反面、コメントが書けない、末尾カンマで構文エラーになる、複数行文字列を \n で書き下す必要がある、といった「設定ファイルとしての書きにくさ」があります。tsconfig.json などで JSONC (コメント付き JSON) や JSON5 が使われるのはこのためです。

TOML は INI ファイルに近い見た目で、テーブルヘッダ [server.database] のおかげで深いネストでもインデントに頼らずに書けます。Rust Cargo や Python の pyproject.toml で標準採用されてから一気に普及しました。一方で配列の中に複数のテーブルを並べる ([[products]]) ような構造は記法に独特さがあり、深く動的なツリーには向きません。

ユースケース別の推奨

Kubernetes マニフェスト / GitHub Actions / Docker Compose / Ansible Playbook: YAML 一択。ツール側がそもそも YAML しか受け付けないことが多く、選択の余地はありません。代わりに 暗黙の型変換に対する自衛 が必要です。バージョン番号 1.10 を引用符なしで書くと float の 1.1 になりますし、NO / ON も罠です。基本ルールは「文字列にしたいものは必ずクォートで囲む」。

Web API レスポンス / 設定ファイルでもアプリ間でやりとりするもの / package.json: JSON。仕様が最小で、ほぼすべての言語に標準ライブラリのパーサがあり、機械が読む経路では事故が一番少ない。手書き編集が必要なら JSONC や JSON5 にしてもよいですが、保存時に標準 JSON へ正規化する 運用がおすすめです。

Rust Cargo / Python pyproject / Hugo の設定 / 個人ツールの設定ファイル: TOML。1 階層〜2 階層のネストで収まる構造に向いており、コメントが自然に書けます。pyproject.toml のように「ビルド設定 + 依存関係 + ツール設定」をひとつのファイルに乗せる用途でも、テーブルヘッダで論理的に区切れて読みやすい。

VS Code / Neovim / ESLint の設定: JSON または JSON5 / JSONC。エディタ側が拡張 JSON を許容しているので、コメントや末尾カンマを使ってしまってよい。プロジェクト共有時は CI で JSON にダウンキャストする か、最初から .json5 拡張子で明示するとレビューしやすくなります。

nosend-tools で完結する変換と落とし穴

3 フォーマット間の変換は手書きでやると型変換ミスを起こしがちです。yaml-json-convert は YAML ↔ JSON を相互変換し、整形済みの出力を返します。TOML との相互変換が必要なら toml-json-convert を経由して JSON をハブにする 2 段構成が安定です。出力を後段でクリーンに整えたいときは json-format でインデントとキー順を統一できます。

ブラウザだけで変換することの最大の利点は、設定ファイルに含まれがちな機微情報 (本番 DB のホスト名・内部 API のエンドポイント・サービスアカウント名) を一切ネット越しに送らないことです。アップロード型のオンラインコンバータは入力を運営側ログに記録できる構造で、規約で明示的に解析・改善利用に組み込んでいるケースもあります。実装は GitHub で公開しており、DevTools の Network タブで「変換中にどこにも送信されていない」ことを目視確認できます。

最後に YAML を扱うときの自衛として、信頼できない YAML を yaml.load で読み込まない ことを覚えておいてください。PyYAML の yaml.load は任意 Python オブジェクトの構築を許す既定挙動で、過去に多数の RCE 脆弱性が報告されました。yaml.safe_load を使う、Go なら gopkg.in/yaml.v3 の strict モード、Node.js なら js-yamlsafeLoad 系 API を使うのが基本ルールです。