プロジェクトによっては設定に.jsonファイルを使い、別のプロジェクトでは .yaml.ymlを使うことに気づいたことがあるでしょう。どちらのフォーマットも構造化データを表現し、 どちらも人間が読めます。では実際の違いは何で、どちらを選ぶべきでしょうか?

私はどちらも幅広く使ってきました——JSONはAPIやデータ交換の日常的なフォーマットとして、 YAMLKubernetesマニフェストGitHub Actions、 Docker Composeに使っています。似た問題を解決しますが、性格は大きく異なります。

並べて比較:同じ設定を両フォーマットで

JSONで書いたデータベース設定オブジェクトです:

json
{
  "database": {
    "host": "localhost",
    "port": 5432,
    "name": "myapp",
    "ssl": true,
    "pool": {
      "min": 2,
      "max": 10
    },
    "replicas": ["replica1.db", "replica2.db"]
  }
}

同じ設定をYAMLで書くとこうなります:

yaml
database:
  host: localhost
  port: 5432
  name: myapp
  ssl: true
  pool:
    min: 2
    max: 10
  replicas:
    - replica1.db
    - replica2.db

YAMLの方が明らかにすっきりしています。ほとんどの文字列にクォートが不要で、波括弧もカンマもありません。 人間が定期的に編集する設定ファイルでは、この明瞭さが蓄積されます。ただしYAMLはその代わりに、 内部的にはかなり複雑になっています。

YAMLが輝く場面

  • 人間が編集する設定ファイル。 CI/CDパイプライン(GitHub Actions、GitLab CI)、Kubernetesマニフェスト、Docker Compose、Ansibleのプレイブック。すべてYAMLです。偶然ではありません——これらは人間が手で書くファイルです。
  • コメント。 YAMLは#でコメントをサポートします。設定ファイルでなぜその値なのかを説明したい場合に非常に重要です。JSONはコメントをまったくサポートしません。
  • 複数行の文字列。 YAMLには自然に読める複数行コンテンツのためのブロックスカラーがあります。JSONでは\nエスケープシーケンスが必要です。
  • 視覚的なノイズが少ない。 ほとんどの文字列をクォートする必要がなく、閉じ括弧もなく、末尾カンマを気にする必要もありません。
  • アンカーとエイリアス。 YAMLでは&anchor*aliasを使って値を一度定義して他の場所で参照できます——DRYな設定ファイルに便利です。

JSONが勝る場面

  • 厳格さ。 JSONは任意のデータ構造に対して有効な表現が1つだけです。YAMLは同じものを書く方法が12通りあり、チーム間で不整合が生まれます。
  • インデントの罠がない。 JSONは波括弧と角括弧を使います。YAMLはインデントを使うため、スペース1つのミスで設定全体が静かに壊れる可能性があります。
  • パースのパフォーマンス。 JSONパーサーは高速でシンプルです。YAMLパーサーは複雑で——YAML 1.1には悪名高い暗黙的な型変換ルールがあります。
  • ユニバーサルなライブラリサポート。 すべての言語に依存関係ゼロの実績あるJSONパーサーがあります。YAMLライブラリは品質と仕様への準拠度がまちまちです。
  • ツールサポート。 リンター、フォーマッター、スキーマバリデーター——JSONのツールエコシステムはより成熟しており、広く利用可能です。
  • APIのペイロード。 JSONはWeb APIの共通言語です。HTTP越しにYAMLを送るのは慣例に反し、摩擦を生みます。

あなたを痛い目に遭わせるYAMLの落とし穴

YAMLには実際の本番インシデントを引き起こした、真に驚くべき動作があります。 そのほとんどは YAML 1.1の暗黙的な型ルールに由来し、 YAML 1.2で厳格化されました。 重要な用途にYAMLを使う前に、これらを把握しておいてください:

ノルウェー問題 YAML 1.1(多くの古いツールが使用)では、文字列NOが ブーリアンのfalseとしてパースされます。NO(ノルウェー)のような国コードが 静かにブーリアンに変換されます。YAML 1.2では修正されましたが、すべてのパーサーが追いついているわけではありません。
yaml
# YAML 1.1 implicit type coercion — all of these become booleans:
enabled: yes   # → true
disabled: no   # → false
country: NO    # → false (!)  ← the Norway Problem

# Safe practice: quote strings that look like booleans
country: "NO"
enabled: "yes"
  • 8進数の整数。 YAML 1.1では01010ではなく8(8進数)としてパースされます。ファイルパーミッションなどに関係します。
  • タブ対スペース。 YAMLはインデントにタブを禁止しています。コードエディタからタブが1つ混入するだけで、ファイルが静かに壊れるか謎のエラーが出ます。
  • 暗黙的なnull。 YAMLで値が空だとnullになります。手動編集時に気づきにくいです。
  • 文字列と数値の曖昧さ。 port: 8080は整数になります。version: 1.0はfloatになるかもしれません。文字列の"1.0"が欲しい場合もあります。重要な場合は必ずクォートしてください。

実践的な決断ガイド

YAMLを選ぶ場面:

  • 人間が直接編集する設定ファイルを書くとき:CI/CD、Kubernetes、Docker Compose、Ansible
  • ファイルに設定を説明するコメントを入れたいとき
  • 複数行の文字列値が多いとき
  • 作業しているエコシステムがすでにYAMLを使っているとき(慣例に逆らわない)

JSONを選ぶ場面:

  • APIでデータを送受信するとき
  • データがプログラム的に生成・消費される場合(人間が編集しない)
  • 異なるツールや言語間でパースの一貫性を保証する必要があるとき
  • JSONを標準とするエコシステムで作業するとき:npm(package.json)、VS Code(settings.json)、Angular、TypeScript

2つの間での変換

YAMLを話せないツール向けにYAML設定をJSONに変換する必要がありますか? YAML to JSON コンバーターを使ってください。逆方向は? JSON to YAML コンバーターが対応します。 YAMLフォーマッターは貼り付けたYAMLがずれてしまったときにも便利です。 そしてYAMLがパースされない場合、 YAMLバリデーターが問題の正確な場所を教えてくれます。

まとめ

JSONとYAMLは競合ではなく補完的な関係にあります。データ交換——API、プログラム的なデータ保存、シリアライゼーション——にはJSONを。人間が読んで編集する設定ファイルにはYAMLを使いましょう。成熟したプロジェクトの多くは両方を使っています:依存関係にはpackage.json、CIには.github/workflows/*.yml。それぞれのフォーマットが何に最適化されているかを理解すれば、選択は自然と明らかになります。