ダグラス・クロックフォードがJSONを普及させ、なぜWebアプリやAPIのデフォルトになったのかを解説します。さらに、今日的にJSONを正しく使うための実践的なヒントも紹介します。

JSON(JavaScript Object Notation)は、キーと値の組み合わせやリストを使ってデータをプレーンテキストで軽量に表現する方法です。
ウェブアプリを作るなら――「データ形式」についてあまり意識していなくても――JSONはおそらく既にプロダクトをつなぐ接着剤になっています。フロントエンドがデータを要求する方法、バックエンドが応答する方法、モバイルアプリが状態を同期する方法、サードパーティのサービスがイベントを送る方法。JSONが明確で一貫していればチームは速く出荷できます。乱雑だと、全ての機能に対して「そのデータが何を意味するのか」で時間がかかります。
一目で読める小さな JSON オブジェクトの例です:
{
"userId": 42,
"name": "Sam",
"isPro": true,
"tags": ["beta", "newsletter"]
}
技術的な文脈がなくても、ユーザーに ID、名前、ステータスフラグ、タグの一覧があることは推測できるでしょう。
あなたは以下を学びます:
目標はシンプルです:JSON が単に何かを理解するだけでなく、なぜほとんどのアプリがそれを“話す”のかを理解し、チームが繰り返し犯す一般的なミスを避けられるようにすることです。
ダグラス・クロックフォードは JSON の背後にあるすべてのアイデアを「発明」したわけではありませんが、同じくらい重要なことをしました:シンプルで実用的なパターンを可視化し、名前をつけ、主流へ押し上げたのです。
ウェブアプリの初期には、ブラウザとサーバー間でデータを移動させるための選択肢が扱いにくいものでした。XML は一般的でしたが冗長でした。カスタムの区切り文字ベースのフォーマットはコンパクトでしたが脆弱でした。JavaScript でデータをコードとして評価することは技術的に可能でしたが、「データ」と「実行可能スクリプト」の境界があいまいになり、バグやセキュリティの問題を招きかねませんでした。
クロックフォードはよりクリーンな道を見出しました:JavaScript リテラル構文の小さなサブセットを使い、オブジェクト、配列、文字列、数値、真偽値、null といったプレーンなデータを余計な機能なしに表現できるようにしたのです。
クロックフォードの最大の貢献のひとつは技術的な面というより社会的な面でした:彼はそれを JSON(JavaScript Object Notation) と名付け、json.org に明確なドキュメントを公開しました。これによりチームは共通の語彙(「JSON を送る」)を持ち、短く読みやすく実装が厳密に可能な参照を得ました。
また彼は、JSON を JavaScript というプログラミング言語から独立したデータ形式として推進しました:多くの言語がパースと生成をサポートし、一般的なデータ構造に自然にマッピングできたのです。
採用は、チームが長期的にフォーマットに賭けても安全だと感じると加速します。JSON は次のような広く知られた節目を経て「安全な選択肢」という地位を得ました:
クロックフォードの働きかけと、これらの標準および増え続けるパーサーのエコシステムが組み合わさり、JSON は便利な慣習から、特に HTTP API 間でのやり取りにおけるデフォルトの手段へと移行しました(/blog/json-and-apis で後述)。
JSON がデフォルトになる前、ウェブはチーム間でスケールするには重すぎたり、一貫性がなかったり、カスタム過ぎるさまざまなフォーマットに頼っていました。
標準的な選択肢としては XML が大きな存在でした。言語横断で動作し、ツールもあり、ネスト構造を表現できましたが、多くの儀式を伴いました。
同時に、多くのアプリは カスタムクエリ文字列(特に初期の AJAX リクエスト)としてデータを渡していました:URL や POST ボディに詰め込まれたキー/バリューのペアです。他にも アドホックなテキスト形式(ここではカンマ区切り、そこではパイプ区切り)を作り、エスケープルールを手作業で実装することがあり、理解できるのは作った開発者だけ、という状況がよくありました。
問題は理論的なものではありませんでした:
ほとんどのアプリはあらゆる種類のドキュメント構造を表現するフォーマットを必要としているわけではありません。予測可能にオブジェクト、配列、文字列、数値、真偽値を素早く一貫して送れることが重要で、解釈の余地を減らすシンプルさがチームの決定(とミス)の数を減らします。
\u003cuser\u003e
\u003cid\u003e42\u003c/id\u003e
\u003cname\u003eAda\u003c/name\u003e
\u003cisActive\u003etrue\u003c/isActive\u003e
\u003c/user\u003e
{
"id": 42,
"name": "Ada",
"isActive": true
}
どちらも同じ意味を表しますが、JSON の方が読みやすく、生成しやすく、ほとんどのアプリがメモリ上でデータをモデル化する方法に近いのです。
JSON の長持ちする力は偶然ではありません。実際に成功するのは意図的に小さく設計されたからです:実際のアプリデータを表現するのに必要十分な構造だけを提供し、無限のバリエーションを招かないようにしたのです。
JSON は多くのアプリがデータを考える方法にきれいにマップする最小のツールキットを提供します:
name, email のような連想配列)true/falseそれだけです。日付、コメント、カスタム数値型、参照などはありません。このシンプルさが言語やプラットフォーム横断で JSON を実装しやすくします。
JSON はログや API レスポンスを人がざっと確認できるほど読みやすく、同時に機械が高速にパースできるように設計されています。余計な儀式を排しつつも、明確な区切り({}, [], :)を保持することでパーサーが速く信頼できるものになります。
トレードオフとして、JSON があまりにミニマルであるため、タイムスタンプ、金額、識別子などについてはチーム間で慣習を決める必要があります(例えば日付は ISO-8601 にするなど)。
JSON の厳しいルール(文字列は必ずダブルクオート、末尾のカンマ禁止、コメントなし、限定された型の集合)は曖昧さを減らします。曖昧さが少ないほど、異なるシステムがデータを交換する際の「自分の環境では動く」問題が減ります。
JSON は JavaScript のオブジェクト構文に似ていますが、JSON は JavaScript ではありません。JSON は言語に依存しないデータ形式で、Python、Java、Go、Ruby など、整合的なシリアライズと相互運用が必要なあらゆる場所で使えます。
JSON が勝ったのは最も多機能だからではありません。ウェブアプリの作り方に自然にマッチしたからです:JavaScript を多用するブラウザがシンプルな HTTP リクエストでサーバーと話す構成にフィットしたのです。
ブラウザが JavaScript を標準搭載すると、クライアント側は構造化データを表現する手段(オブジェクト、配列、文字列、数値、真偽値、null)を持つようになりました。JSON はそれらのプリミティブを密接に模倣したため、ブラウザが理解するデータとサーバーが送るデータの間の移動が自然になったのです。
初期の Ajax スタイルのアプリはこれを加速しました。サーバーがフル HTML ページを返す代わりに、UI がレンダリングするための小さなペイロードを返せるようになりました。例えば以下のようなレスポンスは即座に有用でした:
{
"user": {"id": 42, "name": "Sam"},
"unreadCount": 3
}
JSON の構文は JavaScript に似ていますが言語中立です。フロントエンドと相互運用する必要がある他の言語のサーバーやクライアントが出てくると、すぐに JSON ライブラリが現れ、標準装備となりました。JSON 文字列をネイティブのデータ構造に変換するのは大抵ワンコールの操作で、生成も同様に簡単です。
フレームワーク、API クライアント、デバッガ、プロキシ、ドキュメントツールが JSON を前提にすると、別のフォーマットを選ぶのは摩擦を生みます。開発者はブラウザのデベロッパーツールでペイロードを調べ、テストにコピペし、成熟したライブラリに頼ってエンコードやデコード、エラーハンドリングができます。
単一の JSON レスポンスがウェブ UI、モバイルアプリ、内部サービス、サードパーティ統合のいずれにも最小限の変更で対応できる点は大きな利点です。これにより「1つのバックエンド、複数のフロントエンド」を作るチームにとって JSON は安全な選択肢となり、クライアントとサーバー間の契約のデフォルトになりました。
JSON が勝ったのは豪華だからではなく、ウェブが既に動いている方法にきれいにフィットしたからです。HTTP はリクエストを送りレスポンスを受け取る仕組みを提供し、JSON はそのボディ(リクエストまたはレスポンス)を構造化データとして表現する簡単で予測可能な方法を提供します。
API リクエストは通常メソッドと URL(例:GET /users?limit=20)を含みます。サーバーはステータスコード(200 や 404 など)、ヘッダ、任意のボディで応答します。
ボディが JSON のとき重要なヘッダは:
Content-Type: application/jsonこのヘッダはクライアントに受け取ったバイト列をどう解釈するかを指示します。クライアント→サーバーの送信でも Content-Type: application/json を付ければ「JSON を投稿している」とサーバーに伝わり、サーバーは一貫してパースできます。
JSON は多くの API に共通する繰り返しパターンに特に適しています。
ページネーションはリストをメタデータで包むことが多いです:
{
"data": [{"id": 1, "name": "A"}],
"pagination": {"limit": 20, "offset": 0, "total": 153}
}
フィルタリングとソートは通常 URL のクエリ文字列で行い、結果は JSON 配列(あるいは data フィールド)として返されます。例:GET /orders?status=paid&sort=-created_at。
エラー応答はクライアントがメッセージを表示しリトライを処理できるよう、標準的な形を持つと便利です:
{
"error": {
"code": "invalid_request",
"message": "limit must be between 1 and 100",
"details": {"field": "limit"}
}
}
実践的なマッチングは単純です:HTTP は配達と意味(動詞、ステータスコード、キャッシュ)を提供し、JSON はデータ自体の軽量で人が読める構造を提供します。
JSON と XML を比較するとき、しばしば「アプリのためのデータ」対「ドキュメントのためのデータ」という違いが隠れています。どちらも構造化情報を表現できますが、JSON はほとんどのアプリが実際に扱うもの――単純なオブジェクト、リスト、文字列、数値、真偽値、null――によりマッチします。
XML は設計上冗長です。開閉タグを繰り返すとペイロードが大きくなり、ログやネットワークインスペクタでの走査が難しくなります。JSON は同じ意味をより少ない文字数と視覚的ノイズで伝えるので、デバッグ時に助かり、大規模では帯域幅コストを下げる効果もあります。
これは単なる美観の問題ではありません:小さいペイロードは転送が速くなり、パーサーやプロキシの負荷も下がります。
ほとんどのアプリデータは連想配列(キー/値)や配列(リスト)の形をしています:属性を持つユーザー、明細のある注文、コンポーネントのあるページ。JSON はその精神モデルに直接マッピングし、JavaScript や多くの現代言語のネイティブなデータ構造と一致します。
XML でも同じ構造は表現できますが、通常は慣習が必要です:属性と要素の使い分け、リストのための繰り返し子要素、数値かどうかの判定など(すべてテキストなので型付けを追加しない限り)。
XML は文書指向のユースケースで強みを発揮します:混在コンテンツ(テキストとマークアップの混在)、出版ワークフロー、成熟した XML ツールチェーンを必要とするエコシステム(特定のエンタープライズ統合など)。ペイロードがオブジェクトグラフよりドキュメントに近いなら、XML が適していることがあります。
フロントエンド、バックエンド、API 間でアプリデータをやり取りするのが主要な目的なら、JSON が通常はよりシンプルで直接的な選択です。ドキュメントのマークアップが必要だったり、XML に偏ったドメインと統合する場合は XML を選ぶ意味があります。
JSON は「JavaScript オブジェクト」のように見えるため、チームはしばしば JavaScript と同じように扱えると誤解します。ここでバグが忍び込みます:JSON はより厳格で、より小さく、許容が少ないのです。
何度も繰り返される "自分の環境では動く" 問題は次の点から発生します:
{name: "Ada"} は JSON ではありません。{ "name": "Ada" } が正しい形式です。{ "a": 1, } は多くのパーサーで失敗します。// や /* ... */ は無効です。注釈が必要ならドキュメントに置くか、開発時専用のフィールドを別に使ってください。これらの制約は意図的です:パーサーを簡潔かつ言語横断で一貫したものに保つためです。
JSON には数値型は一つだけ(number)です。整数、少数、日付は組み込みではありません。
"19.99")として送る方が安全なことが多いです。"2025-12-26T10:15:30Z")を使い、カスタム形式は避けるべきです。JSON は Unicode をサポートしていますが実運用ではエンコーディングとエスケープに関する落とし穴があります:
" やバックスラッシュ \)をエスケープする必要があることを忘れないでください。常に本物の JSON パーサー(JSON.parse など)を使ってパースしてください。速そうに見えても eval スタイルのアプローチは避けてください。そして公開 API ではエッジで入力を検証し、予期しないフィールドや型がビジネスロジックに入り込まないようにします。
JSON ペイロードは単なる「移動中のデータ」ではなく、チームやシステム、将来のあなた自身との長期的なインターフェースです。長持ちするペイロードと四半期ごとに書き直されるペイロードの違いは、たいてい地味な規律にあります:一貫性、変更管理、予測可能なエッジケース。
命名規則を決めてどこでも守りましょう:
camelCase か snake_case)を選び混在させない。userId を id に変えるのは意味が明白でも破壊的変更です。"count": 3 と "count": "3" のような)と追跡しにくいバグの原因になります。ほとんどのバージョン戦争は差分を付け加えることで避けられます:
/v2/...)を使うか、ヘッダで明確なバージョン情報を渡す。意味を黙って変えないこと。クライアントはエラーが一貫した形で来ると扱いやすいです:
{
"error": {
"code": "INVALID_ARGUMENT",
"message": "email must be a valid address",
"details": { "field": "email" }
}
}
優れた JSON ドキュメントは実際の例(成功レスポンスと失敗レスポンスの両方)を含み、フィールドの完全な形を示します。例を本番挙動と同期させ、どのフィールドがオプショナルか、nullable か、非推奨かを明記してください。実際のレスポンスと例が一致していれば統合は速く安定します。
vibe-coding ワークフローで素早く機能を立ち上げていると、JSON 契約はさらに重要になります:迅速な反復は素晴らしいですが、クライアントとサービスがずれていくと問題になります。
Koder.ai では、チームが一般的に React フロントエンドと Go + PostgreSQL バックエンドを生成し、planning mode で API 形状をロックする前に反復します。スナップショットとロールバック のような機能は「小さな」JSON 変更が破壊的であることが判明したときに役立ち、ソースコードのエクスポート は契約をリポジトリに保持してテストで強制するのを容易にします。
JSON は生成が簡単で、それが強みであると同時に罠でもあります。あるサービスが "age": "27"(文字列)を送り、別のサービスが 27(数値)を期待していると、JSON 自体は何も止めません。その結果はたいてい最悪のタイプのバグになります:本番でクライアントがクラッシュするか、あるいは特定のデータでだけ起きる微妙な UI の不具合です。
バリデーションは、壊れたまたは予期しないデータがそれを頼りにする人たち――フロントエンド、パートナー統合、分析パイプライン、モバイルアプリ――のもとに到達する前に検出するためのものです。
よくある失敗点は、必須フィールドの欠如、キーの改名、型の不一致、ほぼ正しい値(不揃いな日付形式など)です。API 境界での小さなバリデーションステップが、これらを障害から明確なエラーメッセージへと変えます。
JSON Schema は JSON の形を記述する標準的な方法です:必須プロパティ、許容される型、列挙、パターンなどを定義できます。これが有用なのは:
スキーマがあれば、サーバーでリクエストを検証し、テストでレスポンスを検証し、ドキュメントを生成できます。多くのチームは OpenAPI と組み合わせて契約を明示的にし、/docs にスキーマ例をリンクして一貫性を保っています。
すべてのチームが最初から完全なスキーマツールを必要とするわけではありません。実用的な選択肢には:
実用的なルール:まずは例と契約テストから始め、変更や統合が増えてきたら JSON Schema を導入する、という順序が有効です。
JSON は少数フィールドを送るときは「軽量」に感じられます。スケール時――不安定なネットワーク上のモバイルクライアント、高トラフィックの API、分析重視のページ――では、JSON がパフォーマンス問題や信頼性リスクになることがあり、形を整えて送る必要があります。
最も一般的なスケーリング問題は JSON のパースではなく、送り過ぎです。
ページネーションがシンプルな勝ちです:クライアントが数千件を一度にダウンロードしないように予測可能なチャンク(例:limit + cursor)を返します。ネストしたオブジェクトを返すエンドポイントでは部分応答を検討してください:クライアントが今必要なフィールドだけを要求できる(選択フィールドや "include" 拡張)仕組みです。これにより画面が name と status だけを必要としているのに過去の全履歴や設定フィールドを受け取るといったオーバーフェッチを防げます。
実用的なルール:レスポンスはデータベースが結合できる形ではなく、画面が「今」必要とするものに基づいて設計すること。
API が大きな JSON レスポンスを返すなら、圧縮で転送サイズを劇的に削減できます。多くのサーバーは自動で gzip や brotli を使え、ほとんどのクライアントは追加コードなしで処理します。
キャッシュはもう一つの重要なレバーです。基本方針として:
これにより重複ダウンロードが減り、トラフィックスパイクが平滑化されます。
非常に大きな出力(エクスポート、イベントフィード、バルク同期)では、クライアントがドキュメント全体をメモリに読み込む前に処理できるようストリーミングやインクリメンタルパースを検討してください。ほとんどのアプリでは必要ありませんが、 "一つの大きな JSON ブロブ" がタイムアウトし始めたときに有用な選択肢です。
JSON はログに取りやすい反面、それが危険にもなります。ログを製品の表面として扱ってください:
これを適切にやれば、誤ったデータ露出のリスクを下げつつ、デバッグは速くなります。
JSON は「完成」しているわけではなく、安定しています。これから変わるのはその周辺のエコシステムです:より強力なエディタ、より良いバリデーション、より安全な API 契約、そしてチームが偶発的に破壊的変更をしないよう助けるツール群です。
JSON は広くサポートされ、デバッグしやすく、一般的なデータ構造にきれいにマッピングするため、多くのウェブとモバイルアプリでワイヤフォーマットのデフォルトであり続けるでしょう。
最大の変化は 型付き API への移行です:チームは引き続き JSON を送りますが、JSON をより正確に定義する(JSON Schema、OpenAPI、コード生成ツールなどを使う)ことで、形状を当て推量する瞬間が減り、オートコンプリートが効き、エラー検出が早まります――それでも JSON 自体は手放しません。
多数のレコード(ログ、分析イベント、エクスポート)を効率的に送る/保存する必要がある場合、ひとつの巨大な JSON 配列は扱いにくいです。JSON Lines(別名 NDJSON)は 1 行に 1 つの JSON オブジェクト を置くことでこれを解決します。ストリーミング処理しやすく、コマンドラインツールとの相性も良いです。
このチェックリストをスプリント以上の寿命を持つペイロードの事前確認として使ってください:
2025-12-26T10:15:00Z)。null を区別し、その選択を文書化する。さらに深掘りしたければ、/blog にある関連ガイドを参照してください。特にスキーマバリデーション、API のバージョニング、長期互換性のあるペイロード設計などのトピックがおすすめです。