JSONの文法は最小限です。6つの値型、コメントなし、末尾カンマなし、文字列の引用方法に柔軟性なし。この厳格さはマシンにとっての強みであり、人間にとっての弱みです。人間がJSONを読む必要がある場合 — 設定ファイル、API応答、diff — フォーマットが重要です。
この記事では、直面するすべてのフォーマットの決定、エコシステムが何を決定したか、そして議論がまだ続いている場所を扱います。
インデント:2スペースが勝者
タブ vs スペースの戦いはJSONの世界で勝者を迎えました:2スペース。ほぼすべての主要なスタイルガイド、リンター、フォーマッターはデフォルトで2スペースのインデントを使用します:
- Google JSONスタイルガイド — 2スペース
- Prettier — 2スペース(デフォルト)
- ESLint — 2スペース(ほとんどの設定)
- AWS CloudFormation — 2スペース
- Kubernetesマニフェスト — 2スペース
理由は実用的です:JSONは引用符と中括弧ですでに冗長です。4スペースのインデントはネストされたオブジェクトをほとんどのエディターの右端から押し出します。2スペースは水平方向のスペースを無駄にせずに可読性を維持します。
チームが好みで一貫性があるのであれば4スペースを使用してください。必要ならタブを使用しますが、ほとんどのJSONツールはスペースを想定しており、JSONファイル内の混合インデントはパースエラーの原因となることを覚えておいてください。
末尾カンマ:まだダメ
JSONは末尾カンマを許可しません。これは手動で編集されたJSONファイルで最も一般的な構文エラーです。次のように書きます:
{
"name": "Alice",
"items": ["a", "b",],
}
厳格なパーサーはそれを拒否します。"b"の後の末尾カンマと閉じ中括弧}の後の末尾カンマはどちらも違法です。
YAMLは末尾カンマを許可します(ほとんどの言語がそうします)。JSONは許可しません。ツールがJSONC(VS Codeのtsconfig.jsonとsettings.jsonで使用されるコメント付きJSON)をサポートしている場合、末尾カンマは許可されます。しかしプレーンJSON — APIを介して移動する種類 — はそれを容認しません。
最良の防御:これを自動的にキャッチするフォーマッターを使用してください。コミット前にJSONをバリデーターに貼り付けてください。
プリティ vs コンパクト
プリティフォーマットされたJSONには改行とインデントがあります。可読で、diff可能で、デバッグ可能です:
{
"status": "ok",
"count": 42
}
コンパクトなJSONにはトークン間にホワイトスペースがありません。ワイヤ上では小さくなります:
{"status":"ok","count":42}
経験則:
- 人間向け(設定ファイル、ログ、デバッグ中のAPI応答)→ プリティ。
- マシン向け(本番APIペイロード、メッセージキュー、イベントストリーム)→ コンパクト。
- ストレージ(データベース、キャッシュ)→ コンパクト、デバッグ中に手動で読む必要がない限り。
コンパクトJSONは2スペースのプリティフォーマットJSONと比較して約20-30%のサイズを節約します。10KBのペイロードの場合、2-3KBです。数百万のリクエストを通じて、それは積み重なります。手動で編集する設定ファイルの場合、プリティフォーマットJSONの可読性は追加のバイトに値します。
ソートされたキー
オブジェクトキーはアルファベット順にソートされるべきか?
賛成: diffは決定論的です。キーを追加すると、その行だけがgit diffに表示されます。ソートされたキーがなく、途中にキーを挿入すると、その後のすべてのキーがシフトし、ノイジーなdiffが作成されます。
反対: 論理的なグループ化の方が可読です。"name"を最初、"id"を2番目するのは直感的です。アルファベットソートは意味論的理由なしに"address"を"name"の前に配置します。
実用的な答え:マシン生成JSON(API、設定、diff)ではキーをソートしてください。手書きJSONでは論理順を維持してください。 ほとんどのフォーマッター(Prettier、jq、python -m json.tool)にはCIで有効にできる--sort-keysフラグがあります。
キー命名規則
JSONキーは文字列であり、エコシステムは2つの規約に落ち着いています:
- camelCase — JavaScript/Node.jsのデフォルト。
firstName、lastName、createdAt。 - snake_case — Python/Ruby/Rustのデフォルト。
first_name、last_name、created_at。 - kebab-case — JSONでは稀で、URLやCSSではより一般的。APIキーには避けます。
1つを選んでそれに従ってください。ほとんどのAPIはcamelCaseを使用します。JavaScriptコンシューマー向けのREST APIを構築する場合、camelCaseは最小限の抵抗です。Pythonサービスとインターフェースする場合、snake_caseは摩擦を軽減します。
最も糟糕なのは混在させることです:あるエンドポイントでfirstName、別のエンドポイントでlast_name。規約を選び、リンターで強制し、先に進んでください。
数値フォーマット
JSONは整数と浮動小数点数を区別しません。42と42.0はどちらも有効で、ほとんどのパーサーは它们を同一に扱います。しかし可読性にはフォーマットが重要です:
- 整数: 小数点なし。
42、42.0ではなく。 - 浮動小数点数: 必要な桁数を使用してください。
3.14159、3.14159000000000ではなく。 - 大きな数: 数字が巨大な場合は科学的記数法を使用してください。
1e10は10000000000より明確です。
JSONはInfinity、-Infinity、NaNをサポートしません。言語がこれらをシリアライズする場合、出力は有効なJSONではなく、パーサーはそれを拒否します。
文字列:シングルクォート vs ダブルクォート
JSONは文字列にダブルクォートを要求します。これは交渉余地ありません。'hello'は有効なJSONではありません。"hello'は有効です。
リンターやエディターがJSONファイルでシングルクォートを許可する場合、JSONCまたは超集合を解析しており、標準JSONではありません。厳格なJSONを期待するAPIとパーサーはシングルクォート文字列を拒否します。
コメント:まだ許可されていない
JSONにはコメント構文がありません。これは設計によりです(仕様はJSONを「データ交換フォーマット」と定義し、設定言語ではありません)、しかしYAMLを使用する開発者の最も一般的な不満です。
回避策:
"comment"または"_comment"キーを使用してください。不格好ですが有効です。- ツールがサポートしている場合はJSONC(VS Codeのフォーマット)を使用してください。
- コメントが重要な設定ファイルにはYAMLまたはTOMLに切り替えてください。
フォーマッターワークフロー
JSONフォーマットの最良のワークフロー:
- 好きなようにJSONを書いてください。 手動のインデントに時間を無駄にしないでください。
- 保存時にフォーマッターを実行 Prettier、
jq、またはエディターの組み込みフォーマッター。 - フォーマットされた出力をコミット 一貫したdiff、スタイル議論なし。
- CIでバリデーション JSON lintステップが本番に到達する前に末尾カンマと構文エラーをキャッチします。
これによりすべてのフォーマット議論が排除されます。フォーマッターが決定し、他のすべてがコードを書きます。
よくあるエラー
- 末尾カンマ — 手動で編集されたJSONで最も頻繁なパースエラー。
- シングルクォート — JavaScriptオブジェクトリテラルでは有効、JSONでは無効。
- 引用符なしキー —
{ name: "Alice" }はJavaScriptであり、JSONではありません。 - コメント —
// これはJSONではありませんや/* これも違います */。 - 混合インデント — 同じファイルでタブとスペースを混在させる。
デプロイ前にJSONをバリデーターに貼り付けてください。1秒で済み、謎の400エラーの30分のデバッグを節約できます。