開発者ツール·7 分

開発者のための JSON フォーマットベストプラクティス

JSON フォーマットのベストプラクティスを解説。よくあるミス、検証方法、整形・圧縮、API 運用のコツを実例で学べます。

JSON とは何か?なぜフォーマットが重要なのか?

JSON(JavaScript Object Notation)は、Web における事実上のデータ交換フォーマットです。軽量で人間が読みやすく、ほぼすべてのプログラミング言語がネイティブにサポートしています。REST API の構築でも、設定の保存でも、フロントエンドとバックエンドのデータ連携でも、JSON は常に第一候補です。

ただし「読みやすい」は書き方次第です。ミニファイ(minify)された 1 行の JSON は 4 KB かもしれません。同じデータを 2 スペースでインデント整形すれば 8 KB になります。どちらも正しい JSON です。違いは、夜中の障害対応で次の開発者——将来の自分を含む——が読めるかどうかです。

良いフォーマットは見た目だけの問題ではありません。直接的に影響します。

  • デバッグのしやすさ:整形済みのペイロードは一目で構造が分かります。ネストしたオブジェクトも把握しやすく、欠落したキーやタイプミスもすぐに目に入ります。
  • Diff の可読性:ミニファイ済み JSON のコードレビューには意味がありません。2 スペースインデントの diff なら、どのフィールドが変わったかが一目で分かります。
  • エラーの位置特定:パースに失敗した時、行番号・列番号はドキュメントが整形されている前提で初めて意味を持ちます。
  • コラボレーション:チームで一貫したスタイルなら、誰も作業前に再フォーマットする必要がありません。

要するにフォーマットは「コミュニケーション」です。コードと同じように JSON を扱いましょう。

よくある JSON のエラー

経験豊富な開発者でもやるミスがこちら。JavaScript では合法なため、エディタが警告を出さないことが多いです。

末尾のカンマ

配列やオブジェクトの最後の要素に続くカンマは JavaScript では合法ですが、JSON では許されません。

```json // 無効 { "name": "Ada", "age": 36, } ```

修正は単純、そのカンマを消すだけです。多くの linter が検出します。検出しないなら linter を変えましょう。

文字列がシングルクォート

JSON の文字列はダブルクォートでなければなりません。シングルクォートは JavaScript の流儀であって JSON の流儀ではありません。

```json // 無効 { 'name': 'Ada' } ```

JavaScript のオブジェクトリテラルや、シングルクォートでレンダリングされた Python の辞書から値をコピーした時にやりがちです。キーも文字列値も必ずダブルクォートにしましょう。

キーがクォートされていない

JSON のキーは文字列でなければならず、文字列はクォート必須です。

```json // 無効 { name: "Ada" } ```

コメント

JSON はコメントをサポートしません。`//` も `/ /` もパースに失敗します。注釈を残したいなら、`"_comment"` フィールドを使うか、JSON5 / JSONC に乗り換えてください——ただし、消費者が厳格 JSON を期待する可能性があるなら送信側だけにしましょう。

括弧の不一致

`}` の書き忘れや `]` の過不足は「Unexpected end of JSON input」のようなエラーの原因第一位です。整形すれば一瞬で気づけます。

JSON を検証する方法

検証には 2 種類あります。構文的(整形式か?)と意味的(期待する構造と一致するか?)。

構文検証はモダンなエディタで十分です。VS Code は不正な JSON を赤くハイライトします。CLI の `jq` は最初の失敗文字でエラーを返してくれます。オンラインのバリデータは便利ですが、機微なデータには注意。非機微なサンプルだけを貼り付けましょう。

意味検証には JSON Schema(後述)か、型付きのパーサが必要です。TypeScript では `zod` や `io-ts` といったライブラリで期待する形を宣言し、合わないデータを弾けます。これらは最悪クラスのバグ——API が新しいフィールドを返し始めたり、既存フィールドが `null` になり、3 レイヤ下でクラッシュする——を境界で捕まえられます。

おすすめのワークフロー:

  1. デバッグ中は受け取った JSON を整形する。
  2. システムの境界(コントローラ、API クライアント、メッセージハンドラ)でスキーマ検証する。
  3. 内部では一切信用しない。

整形と圧縮の使い分け

コインの裏表で、どちらも便利です。場所が違うだけです。

整形(pretty-print):インデントと改行を加えます。用途:

  • git にコミットするソースファイル
  • 開発中に確認する API レスポンス
  • 後から見直す可能性のあるログ
  • ドキュメントやサンプル

圧縮(minify):すべての空白を削除します。用途:

  • 本番 API レスポンス
  • トークンや Cookie(JWT、セッション)
  • 容量制限のある DB やキャッシュ
  • 1 バイトでも削りたいネットワークペイロード

経験則:開発中は整形、本番では圧縮。大抵のビルドツールは自動でやってくれます。アドホックな作業は、無料の JSON フォーマッタ を一度貼り付ければ双方向に変換できます。

2 つの JSON 文書を比較したいなら、テキスト diff ツール を使えばどのフィールドが変わったかを正確にハイライトできます。ミニファイ済み出力と睨めっこするより圧倒的に楽です。

ネストしたデータの扱い

ネストされたオブジェクトと配列は、JSON の表現力が最も輝く場所——同時にバグが好んで潜む場所でもあります。

原則をいくつか:

  • ネストは浅く。3 階層までなら OK、5 階層になったら外部キーでフラットにしたリストに分解するか、複数のエンドポイントに分けましょう。
  • 配列と null の扱いを統一。フィールドが配列になったり `null` になったりすると、`Cannot read property 'map' of null` の温床です。事前に決める:要素がなければ `[]` を返す、`null` は使わない。
  • 必要ならキー順を安定させる。JSON はキー順を規定しませんが、順序が予測できる方がパーサや diff ツールの挙動が安定します。アルファベット順は安全なデフォルトです。
  • 巨大配列に注意。100 万件・50 MB の JSON 配列は技術的に有効でもストリーミングできません。NDJSON(1 行 1 JSON オブジェクト)やページネーション API を検討しましょう。

API における JSON:Content-Type とステータスコード

HTTP API を作るなら、2 つのヘッダでほぼ完結します。

  • `Content-Type: application/json` —— クライアント(と中間層)にこれから何を返すか伝える。これを付け忘れるのは、本番で最も多い API バグです。
  • `Accept: application/json` —— クライアントが受信できる形式。コンテンツネゴシエーションに使います。

レスポンス側は、ステータスコードと結果を一致させましょう。

  • `200 OK` —— 成功、body にリソースや結果。
  • `201 Created` —— 新規作成、`Location` ヘッダで指し示す。
  • `204 No Content` —— 成功、body なし(DELETE で一般的)。
  • `400 Bad Request` —— リクエストが不正(JSON 不正、必須フィールド欠落)。
  • `401 Unauthorized` —— 有効な資格情報なし。
  • `403 Forbidden` —— 資格情報は有効だが権限不足。
  • `404 Not Found` —— リソースが存在しない。
  • `422 Unprocessable Entity` —— JSON は合法だが意味的に NG(例:年齢が負数)。
  • `500 Internal Server Error` —— サーバ側で何かが壊れた。スタックトレースを絶対に漏らさない。

よくあるパターンはレスポンスを包むこと:`{ "data": ..., "error": null }` または `{ "data": null, "error": { "code": "...", "message": "..." } }`。この形は良いですが必須ではありません。どちらかに統一する方が、都度アドホックに形を変えるよりずっと良いです。

JSON Schema 基礎

JSON Schema は JSON 文書の形と制約を記述するための語彙です。JSON の型システムと思えばいいでしょう。

最小のスキーマ:

```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "required": ["name", "age"], "properties": { "name": { "type": "string", "minLength": 1 }, "age": { "type": "integer", "minimum": 0 } } } ```

これは「ドキュメントは非空文字列の `name` と非負整数の `age` を持つオブジェクトでなければならない」という意味です。format(`"format": "email"`)、enum、正規表現、他のスキーマへの参照で拡張できます。

なぜ必要か?境界で検証すれば、汚染データが拡散する前に止められます。スキーマは「動くドキュメント」としても機能し、API が実際に受け付ける形を、誰かの思い込みではなく正確に記述できます。

ほとんどの言語に JSON Schema バリデータがあります。TypeScript では `zod` のようなツールが人気で、スキーマから TypeScript 型を自動生成してくれます。

日付・数値・特殊文字の落とし穴

JSON は意図的にミニマルです。日付型がないため、誰もが一度はハマります。

  • 日付:ISO 8601 文字列で保存(`"2026-02-01T12:00:00Z"`)。`"02/01/2026"` のような表記は曖昧でロケール依存なので NG。
  • 数値:JSON の数値は十進数で整数型はありません。JavaScript では 2^53 を超える整数は精度が落ちます。ID や金額は文字列が無難。
  • ブール:リテラル `true` / `false` のみ。`"true"` という文字列は自動で変換されません。
  • Unicode:JSON 文字列は Unicode なので、絵文字も CJK もそのまま使えます。ただしエスケープは正確に:`\n` は改行、`\\` はバックスラッシュ、`\u0041` は `A`。迷ったら JSON フォーマッタ に貼り付けて生バイトを確認しましょう。
  • null と欠落:`{"age": null}` と `{}` は別物です。システム内で「不明」をどちらで表現するか統一しましょう。

時間を節約するツール

良いフォーマッタは、使ってみて初めて手放せなくなるツールです。私たちの無料 JSON フォーマッタ はブラウザ内だけで動作します——アップロードなし、登録なし、追跡なし。ミニファイ済みペイロードを貼り付けて、整形済みのツリーを受け取り、コピーするだけ。整形と同時に検証するので、構文エラーは行単位でインライン表示されます。

JSON 文書の 2 バージョン(例:移行前後)を比較するなら、テキスト diff ツール も同じ役割を汎用テキストに対して果たし、行単位で差分をハイライトします。

いずれも、毎日何度も手が届くよう設計された 開発者ツール 群の一部です。

まとめ

JSON フォーマットは小さな習慣ですが、プロジェクト期間全体にわたって複利で効いてきます。開発中は整形、本番では圧縮。境界で検証。一度限りのデータでなければスキーマを書く。日付は ISO 8601、大きな数値は文字列、`null` は意図的に使う。

どれも派手ではありません。しかし次回何かが壊れた時、何時間ものデバッグを節約してくれます——そして何かは壊れるものです。良いニュースは、フォーマッタとスキーマが手元にあれば、修正はたいてい 1 回のペーストで済むということです。