JSON完全ガイド:仕様・構文・エッジケースから実運用のベストプラクティスとセキュリティ対策まで

はじめに — JSONとは何か

JSON(JavaScript Object Notation)は、データの表現と交換のための軽量なテキストフォーマットです。人間が読み書きしやすく、機械が解析・生成しやすい構造を持つことを目的に設計されました。ウェブAPI、設定ファイル、ログ、分散システム間のデータ交換など、現代のソフトウェアで広く用いられています。

歴史と標準化

JSONは2000年代初頭に開発され、もともとはJavaScriptのリテラル表記に基づいています。その後、独立したデータ記述フォーマットとして普及しました。標準化によって仕様が明確化され、代表的な文書としてはECMA-404(The JSON Data Interchange Format)とIETFのRFC 8259(The JavaScript Object Notation (JSON) Data Interchange Format)が挙げられます。これらの文書が現行の参照標準です。

基本構文とデータ型

JSONの構造は非常にシンプルで、主に以下の構成要素で成り立ちます。

  • オブジェクト:キーと値のペアの集合(中括弧 { })
  • 配列:値の順序付きリスト(角括弧 [ ])
  • 値:文字列、数値、真偽値(true/false)、null、オブジェクト、配列
  • 文字列:ダブルクオートで囲まれ、エスケープはバックスラッシュで行う(例:"\u2603")

例:

{
  "name": "Alice",
  "age": 30,
  "active": true,
  "tags": ["developer", "日本"],
  "profile": null
}

注意点:

  • キーと文字列は必ずダブルクオートで囲む(シングルクオートは許可されない)。
  • 数値は整数/小数、指数表記が許容されるが、データベースや言語実装によって扱い(整数型か浮動小数点か)が異なる。
  • NaN、Infinity、関数、コメント、トレーリングカンマは標準JSONでは許容されない(多くの実装で寛容モードがあるが標準外)。

仕様上の重要な点(エッジケース)

  • Unicode:文字列はUTF-8などUnicodeでエンコードされる。エスケープ形式\uXXXXはサロゲートペアを通じてSupplementary Charactersを表現できる。
  • 重複キー:仕様は重複キーの扱いを厳密に定めていない。実装依存で上書きされることが一般的なので、重複キーは避けるべき。
  • 数値の精度:JSON自体は数値の型を規定しないため、64bit整数や任意精度が必要な場合は文字列で表現するなどの対策が必要。
  • トップレベル:RFC 8259 は JSON テキストは 1 つの値(配列やオブジェクトが典型)であることを要求している。

利用例とエコシステム

JSONはほぼすべてのプログラミング言語で扱えるライブラリが存在します。主なライブラリ・ツールの例:

  • JavaScript:組み込みの JSON.parse / JSON.stringify、JSON reviver/replacer 機能
  • Python:json モジュール(標準)、ujson、orjson などの高速実装
  • Java:Jackson、Gson、org.json 等
  • C++:RapidJSON、nlohmann/json 等
  • Rust:serde_json
  • コマンドライン:jq(フィルタリング/変換)

拡張と関連規格

  • JSON Schema:データの構造と制約を定義するための仕様。バリデーションやドキュメンテーションに有用(json-schema.org)。
  • JSON Pointer / JSON Patch:JSON ドキュメント内の位置参照や差分(パッチ)表現を規定(RFC 6901、RFC 6902)。
  • JSON-LD:リンクドデータのためのJSONベース表現。語彙や意味づけを付与するのに使われる(W3C)。
  • NDJSON / JSON Lines:ストリーミング用途で1行ごとにJSONを並べる形式(ndjson.org)。
  • バイナリ代替:BSON(MongoDB)、MessagePack、CBOR など、効率や型を重視したフォーマットも存在。

メリット

  • 可読性:テキスト形式であり人間が読みやすい。
  • 普及度:多くのAPIやツールが標準でサポート。
  • 言語非依存:ほぼ全言語で扱えるライブラリが存在。
  • シンプルさ:仕様が比較的単純で学習コストが低い。

デメリット・注意点

  • 型情報が限定的:日付やバイナリなどは標準で型がないため表現方法に合意が必要。
  • 性能と容量:テキストベースのためバイナリ形式に比べてサイズが大きく、解析コストが高い場合がある。
  • セキュリティ:JSONPやevalを使ったパース、信頼しない入力のそのままHTML埋め込みはXSSにつながる。CSRFや不正なデータによるDoSも注意。
  • 互換性問題:コメントやトレーリングカンマを許す実装と標準実装の違いにより、互換性問題が生じることがある。

セキュリティ上の実務的注意点

JSONを安全に扱うためのポイント:

  • 信頼できないJSONをevalで処理しない。必ず安全なパーサ(各言語の標準ライブラリ等)を用いる。
  • JSONPはCORSの代替として古く使われたが、クロスサイトスクリプティングのリスクが高いため原則使用しない。代わりにCORSヘッダを利用する。
  • 大きな数値や深いネストを含むJSONはパーサのリソースを枯渇させる可能性があるため、サイズや深さの制限を設ける。
  • レスポンスのContent-Typeは application/json を正しく返す(charset 指定は通常不要で推奨されない)。

実運用でのベストプラクティス

  • API設計ではスキーマ(JSON Schema等)を用いて構造を明確にし、ドキュメント化する。
  • 日付や高精度数値はISO 8601文字列や文字列表現で明示する(型情報が無いため)。
  • クライアント・サーバ間で互換性を保つため、後方互換性を意識したフィールド追加/廃止のポリシーを定める。
  • バイナリデータはBase64でエンコードせず、必要であれば外部ストレージの参照URIを返す方が効率的。
  • ストリーミングが必要な場面ではNDJSONやチャンク化されたJSONを検討する(ただしパーサ側の対応が必要)。

まとめ

JSONはそのシンプルさと普及度から現代のITシステムで標準的に使われています。一方で型の制約やセキュリティ、性能面での注意点も存在します。仕様(RFC 8259 / ECMA-404)を理解し、JSON SchemaやJSON-LD等の関連技術を適切に組み合わせることで、可読性と堅牢性を両立した設計が可能です。

参考文献