一言でいうと
JSONとは、データを構造化して交換するための軽量なテキストベースのフォーマットで、人間にも読みやすく、マシンにもパース(解釈)しやすいのが特徴です。
こいつが解決する問題
ウェブの黎明期(90年代後半から2000年代初頭)、ページ全体をリロードせずにウェブサイトで新しいデータを取得したいと思ったら、AJAX(Asynchronous JavaScript and XML)という技術を使っていたはずです。そしてその名の通り、データフォーマットにはXMLが選ばれていました。
XMLは強力ですが、同時に...とにかく記述が冗長(verbose)なんです。ゴテゴテしてるというか。開始タグ、終了タグ、属性、名前空間でいっぱいです。ブラウザの言語であるJavaScriptでこれをパースするのは、骨の折れる作業でした。扱いにくいドキュメントツリーをたどらなければならず、どうにもネイティブな感じがしませんでした。
<!-- これでたった一人のユーザーです。何千人ものリストを想像してみてください。げっそりしますね。 -->
<user id="123">
<username>coder_dave</username>
<isActive>true</isActive>
<roles>
<role>admin</role>
<role>editor</role>
</roles>
</user>
2001年頃、Douglas Crockfordという開発者があるプロジェクトに取り組んでいて、もっとシンプルな方法でブラウザにデータを渡す必要がありました。彼は素晴らしいことに気づきました。JavaScriptには、データを表現するための完璧な方法がすでにあるじゃないか、と。そう、オブジェクトリテラル構文です。JavaScriptのオブジェクトそっくりの文字列としてデータを送れたらどうだろう?
これがJSON(JavaScript Object Notation)の誕生の瞬間でした。サーバーはこんなテキストを送ることができます:
{
"id": 123,
"username": "coder_dave",
"isActive": true,
"roles": ["admin", "editor"]
}
...そしてブラウザは、最小限の労力で、それをすぐに扱えるネイティブなJavaScriptオブジェクトに変換できたのです。それは無駄がなく、クリーンで、ウェブのネイティブ言語に完璧にマッチしていました。このシンプルさがウェブAPIのカンブリア爆発を引き起こし、動的なシングルページアプリケーション、モバイルバックエンド、そして私たちが知る現代のインターネットのほぼ全てを動かす原動力となったのです。JSONは単に技術的な問題を解決しただけではありません。ソフトウェアの全く新しい世代への道を切り開く、潤滑油の役割を果たしたのです。
内部の仕組み
その核心は、データをテキストとして書き留めるための一連のルール、ただそれだけです。そのルールがシンプルであることこそが、JSONがこれほど成功した理由です。
基本要素:キーとバリュー
JSONの全世界は、キーとバリューのペアという一つのシンプルな構造で成り立っています。
"key": value
- キーは常にダブルクォートで囲まれた文字列です。これは譲れません。
- バリューには、いくつかの特定のデータ型が使えます。
このペアで、"name": "Luke Skywalker" や "age": 19 のように、一つの情報を表現します。
データ型
JSONはバリューの型に厳格です。何でもかんでも放り込めるわけではありません。使えるのは6つの基本データ型とnullだけです。
| 型 | 例 | 説明 |
|---|---|---|
| 文字列 | "The force is strong with this one." |
任意のテキスト。必ずダブルクォートで囲みます。 |
| 数値 | 1138 or 3.14 |
整数または浮動小数点数。区別はありません。 |
| 真偽値 | true or false |
常に小文字。2値の状態を表します。 |
| 配列 | ["Tatooine", "Dagobah", "Bespin"] |
順序付けられた値のリスト。[]で囲みます。 |
| オブジェクト | { "weapon": "lightsaber", "color": "green" } |
順序のないキーとバリューのペアの集まり。{}で囲みます。 |
| Null | null |
値が意図的に存在しないことを表します。 |
以上です。何が欠けているか気づきましたか?関数、日付(文字列として送信されます)、undefined、そして最も有名なのがコメントです。このミニマリズムはバグではなく、仕様です。これにより、フォーマットが曖昧でなくなり、どんなプログラミング言語でも簡単にパースできるようになっています。
データの構造化:オブジェクトと配列
本当の力は、これらの型をネスト(入れ子に)することで発揮されます。キーとバリューのペアにおけるvalueは、別のオブジェクトや配列にすることができます。これにより、任意に複雑なデータ構造を構築できます。
オブジェクト({...})は、一つの「モノ」に関する関連データをグループ化するために使います。辞書のエントリやプロフィールのようなものだと考えてください。
配列([...])は、順序付けられたアイテムのリストに使います。配列内のアイテムはどんな型でも構いません。複数の型が混在していてもOKです(ただし、通常は同じ型で揃えるのが良い習慣です)。
もう少し複雑な例を見てみましょう:
{
"squadName": "Star Wars Heroes",
"formed": 1977,
"active": true,
"members": [
{
"name": "Luke Skywalker",
"age": 19,
"secretIdentity": null,
"powers": [
"Jedi mind tricks",
"Piloting",
"The Force"
]
},
{
"name": "Han Solo",
"age": 29,
"secretIdentity": null,
"powers": [
"Blaster accuracy",
"Sarcasm",
"Kessel Run under 12 parsecs"
]
}
]
}
ほら、この通り。外側のオブジェクトが部隊について記述しています。そのプロパティの一つである"members"は配列です。その配列の各要素は、ヒーロー一人一人を表す別のオブジェクトです。そして各ヒーローのオブジェクトは独自のプロパティを持ち、その一つ("powers")は文字列の配列になっています。これがJSONでデータツリーを構築する方法です。
テキストからオブジェクトへ:パース処理
ここでのマジックは、このテキストをプログラムが使える何かに変換することです。
- シリアライズ(Serialization): サーバーサイドのアプリケーション(Python、Java、Goなどで書かれている)がメモリ上にデータを持っています。JSONライブラリを使って、そのデータをJSON形式の文字列にシリアライズします。JavaScriptでは
JSON.stringify()がこれにあたります。 - 転送(Transmission): この文字列は、通常HTTPレスポンスのボディとして、ネットワーク経由で送信されます。
- パース(Parsing): クライアント(ウェブブラウザなど)がこの文字列を受け取ります。組み込みのJSONパーサーを使って、文字列を操作可能なネイティブなデータ構造に戻します。JavaScriptでは
JSON.parse()です。
このシリアライズとパースの2ステップのプロセスが、現代のウェブコミュニケーションの心臓部なのです。
現場で起きた実話
バグだらけのモバイルアプリ
あるスタートアップが、地元のレストランチェーン向けのモバイル注文アプリをローンチしました。ある朝、全ユーザーのアプリが起動時にクラッシュし始めました。開発チームは大パニックに陥りました。サーバーログを見ると、APIは200 OKステータスを返しており、ざっと見た感じデータも問題なさそうでした。何時間も必死にデバッグした後、ついにAPIレスポンスの生テキストを調べました。すると、バックエンド開発者が親切心から、JSONを生成するコードに同僚向けのメモを直接書き込んでいたことが判明しました:// TODO: Confirm weekend hours。このコメントが、最終的なJSON文字列に含まれてしまっていたのです。コードの中では無害ですが、コメントはJSONを不正なものにしてしまいます。アプリの厳格なJSONパーサーが予期せぬ//を見つけて即座に失敗し、エラーメッセージを表示する間もなくアプリをクラッシュさせていたのです。
教訓: JSONパーサーは寛容ではありません。フォーマットが厳格に定義されているのには理由があります。それは相互運用性を保証するためです。たった一つの不正な文字(コメント、末尾のカンマ、シングルクォートなど)でも、正当なパーサーはペイロード全体を拒否します。
国際価格設定の大失敗
アメリカのEコマース企業がドイツに進出していました。彼らのAPIは商品情報をJSONで送信しており、その中にpriceフィールドがありました。19.95ドルの商品なら、JSONは"price": 19.95です。ドイツでのローンチ準備として、ある開発者が、ドイツの慣習(カンマを小数点として使う)に合わせて価格をフォーマットするようにバックエンドを更新しました。APIは"price": "19,95"を返すようになりました。しかし、フロントエンドのコードは依然として数値を期待していました。JavaScriptでは、parseFloat("19,95")はカンマ以降を無視して19と評価されます。突如、ドイツの全商品が、とんでもなく間違った割引価格で表示されることになってしまったのです。
教訓: JSONは生データのためのものであり、表示用ではありません。データ型は重要です。価格は数値なので、数値として(19.95のように)送信すべきです。その数値をユーザーのロケールに基づいて$19.95や19,95 €、19円のようにフォーマットする仕事は、クライアントサイドのアプリケーション(ブラウザやモバイルアプリ)に任せましょう。データと表示ロジックを混ぜてはいけません。
説明できない設定ファイル
ある小さなチームが新しいサービスをセットアップする際、config.jsonファイルを使ってデータベースの接続文字列やAPIキー、機能フラグなどを保存していました。設定が複雑になるにつれ、それぞれの謎めいた設定が何をするのか、なぜ特定の値になっているのかを説明するために、どうしてもコメントを追加する必要がありました。しかし、JSONはコメントを禁止しています。彼らの「解決策」は、config.jsonと同期を取り続けなければならないconfig_documentation.mdファイルを作ることでした。これはすぐに大きな苦痛になりました。最終的に、彼らは自分たちの過ちに気づきました。
教訓: 適材適所でツールを使いましょう。JSONはマシン間のデータ交換(APIレスポンスなど)においては、誰もが認めるチャンピオンです。しかし、コメントや可読性が重要となる、人間がメンテナンスする設定ファイルには、YAMLや単純な.jsファイルのような他のフォーマットの方が、はるかに良い選択であることが多いです。
よくある間違いと落とし穴
- 末尾のカンマ(Trailing Commas): オブジェクトや配列の最後の要素の後にカンマを追加すると(
"key": "value",}など)、不正なJSONになります。これは、JavaScriptのより寛容な構文に慣れている開発者が犯しがちなよくある間違いです。 - コメント: 使えません。
//や/* ... */は仕様の一部ではなく、パースを失敗させます。メタデータを追加する必要がある場合は、{ "_comment": "これは私のメモです", "realData": "..." }のように、データ構造自体の中に含める必要があります。 - シングルクォート: すべてのキーとすべての文字列の値は、必ずダブルクォート(
")を使わなければなりません。JavaScriptでは一般的ですが、シングルクォート(')を使うと不正なJSONになります。 - 未定義(Undefined)のキー:
{"key": undefined}を送信することはできません。通常、シリアライズの過程でこのキーとバリューのペアは省略されます。欠損値を表現するにはnullを使いましょう。 - 数値を文字列として扱う: 数値を文字列として(例:
"id": "123")送ることもできますが、悪い習慣です。受信側のアプリケーションに余計な変換作業を強いることになり、微妙なバグ(例えば、文字列比較では"10" > "9"がfalseになるなど)を引き起こす可能性があります。
なぜ知っておくべきか
どんな形であれコードに触れるなら、JSONに出会うことになります。それはもしではなく、いつ、そしてどれくらいの頻度で出会うか、という問題です。
- ウェブ開発者: APIからJSONを受け取り、フォームからJSONを送信します。アプリケーションの状態全体も、おそらくJSONライクなオブジェクトとして管理されているでしょう。
- バックエンド開発者: JSONを生成するAPIを構築し、他のサービスからJSONを利用します。
- モバイル開発者: バックエンドとは、もっぱらJSONを話すAPIを介して通信します。
- DevOps/SRE: Infrastructure-as-codeツール、CI/CDパイプライン、クラウドプロバイダーのAPIは、すべてJSONまたはそれに類するフォーマットで設定・管理されます。
- データサイエンティスト: ウェブAPIからデータを取得しますが、そのデータはほぼ常にJSON形式でやってきます。
- 好奇心旺盛な非開発者の方: JSONのシンプルなキーとバリューの構造を理解すると、スマホのアプリがどうやってデータを取得しているのか、ウェブサイトがどうやって動的にコンテンツを読み込んでいるのか、その謎が解けるかもしれません。デジタル世界のボンネットの中を覗いてみるようなものです。
JSONは、インターネット上のデータの共通言語(リンガ・フランカ)です。そのルールと目的を知ることは、現代のソフトウェアを構築したり扱ったりするすべての人にとって、基本的なスキルと言えるでしょう。
もっと深く知る
- JSON.org: Douglas Crockfordによるオリジナルの1ページの仕様書。シンプルさの極致です。
- RFC 8259: インターネット上でJSONフォーマットを正式に規定する、IETFの公式な「標準」です。
- MDN: Working with JSON: JavaScript開発者向けの決定版ガイド。
JSON.parse()とJSON.stringify()を解説しています。 - Wikipedia: JSON: 歴史、派生フォーマット(GeoJSONなど)、他のフォーマットとの比較など、素晴らしい概観を提供しています。