JSON ベストプラクティス

更新日:

JSON は API・設定ファイル・ログ・システム間のデータ交換における事実上の標準フォーマットです。シンプルさが普及の理由ですが、同じシンプルさが思わぬ落とし穴を隠しています。暗黙の型変換・曖昧な数値表現・命名の揺らぎ・本番でよく見るパースエラーなど、知っておくべきポイントは多いです。本ガイドでは、経験豊富なエンジニアが JSON を予測可能で保守しやすく保つために実践しているルールをまとめます。

フォーマットの前に必ず検証する

整形されていても JSON として無効ならファイルは壊れたままです。インデントを変えるだけで何かが直ったと思う前に、厳密なバリデーター(本サイトの JSON Formatter & Validator など)で検証してください。よくあるパースエラーは、末尾カンマ(標準 JSON では不可)、シングルクォート(ダブルクォートのみ有効)、キーの引用符忘れ、コメント混入などです。JSON にはコメント構文がありません。コメントが欲しければ「_comment」のようなラッパーキーを使うか、コメントを許容するフォーマット(JSON5・YAML・TOML)に切り替えてください。

命名規則を 1 つに決めて徹底する

ほとんどの JSON API は lower_snake_case か camelCase に収束します。プロジェクトでひとつ選び、隅々まで揃えてください。混在すると消費側を混乱させ、コードジェネレーターも壊れます。snake_case は Python / Ruby 系で多く、camelCase は JavaScript / Java 系で多いです。PascalCase は型付き言語からの生成出力でたまに見るくらいで稀です。kebab-case はキーには避けてください(JavaScript からはブラケット記法でしかアクセスできません)。

数値の扱いに注意する

  • JSON は整数と浮動小数点数を区別しません。多くのパーサは小数点の有無で型を決めます。
  • JavaScript は 2^53 を超える整数で精度を失います。64 ビット ID は文字列としてシリアライズしてください。
  • 先頭のゼロ(無効な JSON)と末尾の小数点(非ポータブル)は避けてください。
  • 通貨額は文字列、または最小単位(円・セント)の整数として送り、浮動小数点誤差を防ぎます。
  • NaN や Infinity は JSON として無効です。シリアライズ前に null や文字列へ変換してください。

順序付きコレクションは配列、キー検索はオブジェクト

配列は「順序が意味を持つ・イテレートする」ことを示し、オブジェクトは「キーアクセス・順序は関係ない」ことを示します。リストを数値文字列キー(「0」「1」「2」)のオブジェクトとして表現するのは古いシリアライザの遺物で、消費側がキー順序からリスト順序を再構築する必要があり脆弱です。逆に、本質的にキー付きのデータを 2 要素ペアの配列でフラット化するのも、オブジェクトのほうが明確であれば避けましょう。

null・キー欠落・空配列を区別する

3 つの状態には別々の意味があります。キーが存在しない(フィールドが提供されなかった)、null(提供されたが値なし)、空配列(提供されたが要素なし)。これらを同じものとして扱うバグは頻発します。API の各フィールドで返しうる状態を文書化し、本当に該当しないフィールドは null ではなくキー自体を省略するのが望ましいです。

進化を前提に設計する

JSON API は時間とともにフィールドを追加していきます。消費側は未知のフィールドを無視する設計に、生成側は既存フィールドの意味を変えずに新しいオプションフィールドを追加する設計にしてください。互換性を破る変更は、エンドポイントの新バージョン(バージョン付き URL や Content-Type)として明示してください。

コントラクトには JSON Schema を使う

2 つのシステムが JSON をやり取りする場合、JSON Schema 文書は両側でマシン検証可能な契約になります。スキーマには必須フィールド・型・許容値・フォーマット・フィールド間の検証ルールまで記述できます。ドキュメント生成・クライアント生成・実行時検証に利用でき、内部サービスでも軽量なスキーマがあるほうが何もないより遥かに保守しやすくなります。

人間向けはプリティ、機械向けはミニファイ

設定ファイル・人間が読むログ・バージョン管理に入れるファイルは、2 / 4 スペースで揃ったインデントで整形してください。帯域が重要なネットワークペイロードはミニファイします。ほとんどの JSON ツールはデータを変えずに両者を切り替えられます。途中で混在させると差分にノイズが入るので避けてください。

信頼できない入力には防御的に

JSON のパースに eval() を使ってはいけません。JavaScript なら JSON.parse()、各言語の安全なパーサを使ってください。受信ペイロードに妥当なサイズ上限を設けます。ネスト深度攻撃にも注意が必要です。多くのパーサは数千レベルの深いネストを受け入れてしまい、素朴な消費側をクラッシュさせ得ます。妥当なネスト深さを超えるペイロードは拒否してください。

よくある質問

見た目は正しいのに JSON のパースが失敗するのはなぜ?
よくある原因は、末尾要素の後にカンマがある、ダブルクォートではなくシングルクォートを使っている、コメントが混入している、キーに引用符がない、ファイル先頭に UTF-8 BOM がある、などです。厳密なバリデーターでエラー行・列を確認してください。
API では camelCase と snake_case のどちらを使うべき?
どちらでも構いません。ひとつを選んで一貫して適用してください。主要な消費者の慣習に合わせるのがよいでしょう。両方の言語(JavaScript と Python など)から呼ばれる場合は、ドキュメントで明示しておくと混乱を防げます。
JSON のキーは重複できますか?
標準では動作は未定義です。パーサごとに、最後のみ残す・最初のみ残す・エラーにする、と動作が異なります。重複キーに依存してはいけません。常に一意なキーを生成してください。
JSON5 は JSON の上位互換ですか?
いいえ。JSON5 はコメント・末尾カンマ・シングルクォート・引用符なしキーを許容しますが、標準 JSON パーサはそれらをすべて拒否します。JSON5 は人間が編集する設定ファイル向けで、システム間の交換には厳密な JSON を使ってください。

まとめ

JSON は「自由形式の塊」ではなく、真面目なデータフォーマットとして扱ってください。積極的に検証し、規約を意図的に選択し、進化に備えて設計します。本サイトの JSON Formatter & Validator は最も多い類のエラーを即座に検出し、すべてブラウザ内で完結します。リリース前に貼り付けて確認してください。

関連ツール