JSON、TOML、YAML、CSON:設定フォーマットの選択
要点:設定ファイルにはコメント、日付、複数行テキストが必要で、そこが JSON の弱点です。JSON、TOML、YAML、CSON を比較し、変換で必ず失われるものを確認します。

要点:機械同士の交換には JSON を使い、人間が保守する設定にはエコシステムに応じて TOML か YAML を選びましょう(Kubernetes と CI は YAML、平坦な構造やネイティブ日付は TOML)。読み取り側が方言に対応しているか不明なときだけ JSONC にフォールバックします。
JSON は機械がデータを交換するために存在し、設定ファイルは人間が人間のために書くものです。二つを混同すると、コメントも書けず、誰も削りたがらない
config.jsonができあがります。
1. まず二種類のファイルを区別する
データ交換と設定は同じ目的を共有しません。同じ人が同じマシンで両方を書くことが多いとしてもです。
| 観点 | データ交換 | 設定 |
|---|---|---|
| 誰が書くか | 値をシリアライズするプログラム | 人間、または生成物を編集する人間 |
| 誰が読むか | 他人のプログラム | 自分のプログラム |
| 何が重要か | 曖昧さゼロ、サイズ、パース速度 | 可読性、コメント、レビュー可能な差分 |
| 変更頻度 | リクエストごと | たまに、レビューを伴って |
| 誤りのコスト | 500 レスポンス | 起動しないサービス |
JSON は左の列でほぼ完璧です。文法は最小、どの言語にもパーサーがあり、コメントがないので「コメントが値からずれる」問題も起きません。右の列では、その厳格さが純粋な摩擦になります。コメントなし、末尾カンマなし、日付なし、複数行テキストは \n で一行に畳まなければなりません。
2. 四つの候補とその構文
- JSON:RFC 8259 と ECMA-404 で定義され、値の型はちょうど六つ。オブジェクト、配列、文字列、数値、真偽値、
nullです。事実上の交換標準で、選択の判断を要さない唯一の形式です。 - TOML:Tom Preston-Werner が作り、v1.0.0 が 2021 年 1 月に公開されました。目標は、意味が明白でハッシュテーブルに一意に対応する最小限の設定形式です。
Cargo.tomlとpyproject.tomlが既定で採用しています。 - YAML:現行仕様は 1.2.2。インデントで階層を表し、コメント、アンカー、複数文書をサポートします。Kubernetes マニフェスト、GitHub Actions、Ansible が依存していますが、代償として仕様が大きく、実装差もあります。
- CSON:CoffeeScript Object Notation で、CoffeeScript のオブジェクトリテラルで設定を書きます。Atom の
config.csonが使っていました。コメント、引用符なしキー、末尾カンマをサポートしますが、エコシステムは JavaScript の世界から出られませんでした。
2.1 能力の比較
| 能力 | JSON | TOML | YAML | CSON |
|---|---|---|---|---|
| コメント | ✗ | ✓ # |
✓ # |
✓ # |
| 末尾カンマ | ✗ | ✓(配列、インラインテーブル) | ✓(フローコレクション) | ✓ |
| 引用符なしキー | ✗ | ✓ | ✓ | ✓ |
| ネイティブ日時 | ✗(文字列のみ) | ✓ 4 種の日時型 | ✓(1.1 では自動パース) | ✗ |
| 複数行文字列 | ✗(\n エスケープ) |
✓ """ と ''' |
✓ ブロックと折り畳みスカラー | ✓ ヒアドキュメント |
| 整数の範囲 | 仕様は無制限、実際は double | 符号付き 64 ビット、無損失が必須 | 任意精度と .inf/.nan |
JavaScript に従う |
| ネスト | 波括弧と角括弧 | テーブル、テーブル配列、ドット付きキー | インデント | インデント |
| インデント依存 | ✗ | ✗ | ✓ | ✓ |
null |
✓ | ✗ | ✓ | ✓ |
| ツールの対応 | すべての言語 | 主要言語 | すべての言語、実装は様々 | JavaScript のみ |
二つのセルには注記が必要です。TOML には null がなく、JSON から変換するときの最も一般的な失敗原因です。YAML の「ネイティブ日付」の振る舞いにより、1.1 のパーサーは 2026-10-31 を自動で日付オブジェクトにするので、言語をまたぐと型がずれます。
3. コメント:JSON 唯一の弱点
結論から言うと、人間がファイルを保守し、値がなぜそうなのかを説明する必要があるなら、標準 JSON を使わないでください。
実践的な道は四つあり、侵襲性の低い順に並べます。
- JSONC に切り替える。標準 JSON にコメントと末尾カンマを加えたものです。VS Code の
settings.jsonとtsconfig.jsonが使っています。代償は、読み取り側がjsonc-parserのようなコメント対応パーサーを使う必要があり、素のJSON.parseでは失敗することです。詳細は JSON5 と JSONC:コメント付き JSONにあります。 - サイドカー文書を保つ。
config.jsonは機械可読のままにし、config.mdが各フィールドの意味と、なぜその値なのかを説明します。両方を同じディレクトリに置き、同じコミットで変更します。 - 説明をスキーマに書く。JSON Schema の
descriptionと$commentキーワードでフィールドを文書化できますが、スキーマが実行時設定と一緒に配布されることは稀で、設定を読む人が目にしない可能性があります。 - TOML か YAML に移る。形式自体が、どのパーサーでも理解されるコメントを提供します。
{
// 8080 に固定:フロントエンドのビルドスクリプトがプロキシ用にこのポートを読む
"port": 8080,
// CI で inode を使い尽くさないよう監視を無効化
"watch": false
}
JSONC も方言です。拡張子は .json のままですが、一部のツールしか理解しません。データがチームの外に出る、またはサービス境界を越えるときは、JSONC と標準 JSON の境界を文書化しなければなりません。
4. 日付と複数行文字列:TOML の得意分野
TOML は日時を第一級の型に昇格させ、四つの変種を持ちます。オフセット付き日時、ローカル日時、ローカル日付、ローカル時刻です。複数行文字列には専用構文があり、改行を保ちます。
title = "json-toolkit"
created = 2026-10-31T09:00:00+08:00
description = """
A JSON toolkit for developers.
Every operation runs locally in the browser.
"""
同じ情報を JSON で表すと、日付を文字列に降格し、改行をエスケープしなければなりません。
{
"title": "json-toolkit",
"created": "2026-10-31T09:00:00+08:00",
"description": "A JSON toolkit for developers.\nEvery operation runs locally in the browser."
}
JSON では "created" はたまたま日付に見える文字列にすぎず、型情報はフィールド契約に置く必要があります。両者がこのフィールドは常に RFC 3339 だと合意しなければなりません。TOML はパーサーに実際の日付オブジェクトを渡し、口頭の合意を必要としません。
YAML も複数行テキストを保持できますが、二つのブロックスタイルは意味が異なります。| は改行を保ち、> は改行をスペースに折り畳みます。間違った方を選ぶと住所や SQL 文が一行に潰れ、レビューで見つけるのが非常に難しいエラーになります。
5. 数値:最も見落とされる違い
JSON 仕様は数値精度に上限を設けていませんが、RFC 8259 は数値を IEEE 754 の倍精度として扱うのが最も安全だと注意もしています。JavaScript では 2^53 - 1 を超える整数が静かに精度を失います。
JSON.parse('{"id":9007199254740993}').id
// 9007199254740992:最後の桁が消えた
TOML は符号付き 64 ビット整数を無損失で扱い、静かに切り捨てるのではなくエラーを出すことを要求します。浮動小数点は binary64 に従い、inf や nan も許されます。YAML 1.1 は古い負担を抱えます。1:30 は 90(六十進数)としてパースされ、真偽値は yes、no、on、off を受け付けます。これが有名な「ノルウェー問題」で、国コード NO が false になります。
金額については、どの形式でも浮動小数点に依存しないでください。整数の最小単位、文字列、データベースの decimal 型を使います。整形と精度はJSON、YAML、XML 変換の境界でより詳しく扱っています。
6. テーブルとネスト:TOML の厳格な境界
TOML はテーブルとテーブル配列でネストを表現します。
[server]
port = 8080
[[routes]]
path = "/parse"
method = "POST"
[[routes]]
path = "/minify"
method = "POST"
変換前に知っておくべき厳格な境界が二つあります。
- TOML 文書のルートはテーブルなので、トップレベルが配列の JSON 文書(
[1, 2, 3]など)には合法的な TOML 表現がありません。{"items": [...]}として包む必要があります。 - TOML に
nullはないので、JSON のnullフィールドは削除するか、空文字列やセンチネル値に置き換え、意味論を利用者側に押し付ける必要があります。
YAML は逆です。ネストの深さは無制限で、アンカーとマージキーが断片を再利用できます。
defaults: &defaults
retries: 3
timeoutMs: 5000
server:
<<: *defaults
port: 8080
アンカーは YAML だけの能力で、変換時に必ず失われます。JSON に参照構文はないので、展開後のファイルは大きくなり、二つのセクションが同じ設定だったことを記録するものが何も残りません。
7. 場面別の選択
| 場面 | 推奨 | 理由 |
|---|---|---|
| 公開 API、メッセージキュー、キャッシュ | JSON | 最大の普遍性、交渉コストゼロ |
| アプリケーション設定、平坦で型付き | TOML | コメント、日付、無損失整数、安定したパーサー動作 |
| Kubernetes、CI、Ansible | YAML | エコシステムが固定され、形式を変えるとツールも変わる |
VS Code、tsconfig.json |
JSONC | ネイティブ対応で、新しい形式を持ち込まない |
| 設定断片の再利用 | YAML | アンカーとマージキーが唯一の既製手段 |
| 生成物、機械専用 | JSON(圧縮) | コメント不要で、サイズとパースコストが最良 |
| レガシーな Atom や CoffeeScript プロジェクト | CSON。ただし移行を計画 | エコシステムは周辺的で、移行コストは時間とともに増える |
経験則:設定フォーマットは個人的な好みではなくエコシステムに選ばせましょう。 Rust を書くなら Cargo.toml、Kubernetes に配備するなら YAML、VS Code 拡張を作るなら JSONC です。エコシステムの制約がない新規プロジェクトでだけ、「どちらが書きやすいか」が本当の問いになります。
8. 変換の境界
| 方向 | 必ず失われる情報 | 助言 |
|---|---|---|
| JSON → TOML | null、トップレベル配列、表現できないキー |
先に構造を正規化し、空フィールドを削除する |
| TOML → JSON | コメント、日付型、inf / nan |
日付を RFC 3339 文字列に変換する |
| YAML → JSON | コメント、アンカーとマージキー、タグ、複数文書 | 先にアンカーを展開し、文書ごとに変換する |
| JSON → YAML | 構造的な損失はないが、日付文字列が自動パースされうる | 日付文字列を引用符で囲む |
| CSON → JSON | コメント、CoffeeScript 式 | 一度だけ移行する。双方向に同期しない |
変換ツールは値を保証しますが、コメントは決して保証しません。ですから「JSON がソースで YAML がビルド成果物」という双方向パイプラインを設計しないでください。一方向にだけ生成するか、単一のソースファイルを保守します。
9. チェックリスト
- [ ] どのファイル種別がどの形式を使うかを文書化し、許可する方言を列挙する。
- [ ] 人間が保守する設定には TOML か YAML を、機械同士の交換には JSON を優先する。
- [ ] JSON の日付は RFC 3339 文字列として保存し、スキーマに形式を記す。
- [ ] 金額と
2^53を超える整数は文字列か最小単位で表し、浮動小数点にしない。 - [ ] 各形式を CI で専用のパーサーにより検証し、YAML に
JSON.parseを使わない。 - [ ] 形式の移行は一方向にだけ行い、古いファイルを削除して二つがずれないようにする。
FAQ
JSON から TOML への変換が一部のフィールドで失敗するのはなぜですか?
TOML には null がなく、TOML 文書のルートはテーブルなので、JSON の null フィールドは削除するか空文字列やセンチネルに置き換え、トップレベル配列は {"items": [...]} として包む必要があります。逆方向ではコメント、日付型、inf/nan も失われます。だから変換は一方向にすべきです。
異なる形式の設定ファイルを二つ保守すべきですか?
いいえ。変換ツールは値を保証しますがコメントは保証しないので、「JSON がソースで YAML がビルド成果物」というパイプラインはずれていきます。一方向にだけ生成するか、単一のソースファイルを保守し、移行後に古い方を削除してください。
JSON の設定ファイルにコメントを追加するには?
標準 JSON にコメントはありません。JSONC(VS Code の方言、jsonc-parser で読む)に切り替える、各フィールドを説明するサイドカー文書を置く、または TOML や YAML に移ることができます。他のシステムに送るファイルは標準 JSON のままにし、説明はドキュメントかスキーマに置きます。
アプリケーション設定には TOML と YAML のどちらが良いですか?
構造が平坦で、ほとんどがキーと値のペアで、ネイティブ日付が重要な場合は TOML を選びます。意味論がより予測可能で、パーサー差も小さいです。深いネスト、複数文書、アンカー再利用が必要な場合、または対象エコシステムが Kubernetes や CI のように YAML 優先なら YAML を選びます。どちらもコメントをサポートするので、実際の差は構造の複雑さとエコシステムの固定度です。
YAML で NO が false になるのはなぜですか?
YAML 1.1 は yes、no、on、off、y、n を真偽値として扱うため、ノルウェーの国コード NO が false としてパースされます。これが「ノルウェー問題」です。YAML 1.2 に従う実装を使うか、誤解されうる文字列をすべて引用符で囲むことで避けられます。
CSON はまだ使う価値がありますか?
新規プロジェクトでは不要です。CSON は CoffeeScript エコシステムに依存し、保守されているツールが少なく、エディタと CI の対応も限られています。Atom の保守が終わってから用途はさらに縮小しました。既存プロジェクトに CSON 設定があるなら、これ以上増やさず、JSON、TOML、YAML への一度きりの移行を計画してください。