JSONとは
JSON(JavaScript Object Notation)は、構造化データを扱うテキスト形式で、RFC 8259が定義しています。オブジェクトをキーと値のペアとして、リストを配列として表現し、6個の記号文字と厳格な型システムを使います。今日のすべてのWeb API、設定ツール、データベースがJSONを読めます――しかも意図的に単純なので、午後のひとときで習得できるほどです。
JSONとはとは
JSONは、データが届くときの形式です。天気アプリが明日の予報を表示するとき、表計算ソフトがレコードを書き出すとき、サービスが設定ファイルを同梱するとき――それらのシステムの間を行き交うテキストは、ほぼ必ずJSONです。波括弧がキーと値を抱え、角括弧がリストを抱え、文字列と数値についての小さなルールのセット。あらゆるプログラミング言語が合意しているルールです。
JSONは2001年頃、JavaScriptのオブジェクトリテラル構文から切り出され、まずRFC 4627として標準化され、のちにRFC 8259として改訂されました。これが現行の版で、同一内容のECMA-404標準と並んで有効です。名前にいまだJavaScriptと刻まれていますが、形式そのものは設計上、言語中立です――Python、Java、Go、C#、SQL、そしてテキストエディターまでもが流暢にJSONを話します。プログラムがデータを交換する既定の手段になったのは、まさにそのためです。
このガイドでは、JSONの正体――6つのデータ型、2つのコンテナ、エスケープのルール――を、コピーして試せる実例つきで解説します。説明が実用的な次の一歩に結びつく場所では、リンク先のツールがブラウザ内で動きます。何もインストールせずに、読んだばかりの例をそのまま整形、検証、変換できるのです。
下の構文ルールを身につける最短の道は、わざと破ってパーサーの反応を見ることです――JSONフォーマッターは、すべてのミスについて正確な行と列を教えてくれます。
すべてのルールを1枚のリファレンスページにまとめたくなったら、JSON構文チートシートがこのガイドを早見表に圧縮しています。
2つのコンテナ:オブジェクトと配列
JSONのすべては2つの構造から組み立てられます。オブジェクトは、波括弧に包まれたキーと値のペアの集合で、順序は保証されません。キーは常に文字列、値にはどんなJSON値でも入れられ、ペアはカンマで区切ります。配列は、角括弧に包まれた値の順序付きリストで、値はどんな型の組み合わせでも構いません。
オブジェクト(キーと値のペア)
{
"name": "Ada Lovelace",
"born": 1815,
"mathematician": true
}配列(順序付きの値)
[ "analytical engine", 1843, null ]
6つのデータ型
スカラーが4つ――string、number、boolean、null――で、残る2つは上で出したコンテナです。初心者が面食らうルールは少ないながら、厳格です。文字列は常にダブルクォートで囲む(シングルクォートは無効)。数値にクォートは不要で、16進では書けない。booleanは小文字のトークンtrueとfalseそのもの。nullは「意図的に空である」ことを意味する、独立した値です。
| 型 | 例 | 覚えておきたいルール |
|---|---|---|
| string | "hello", "café", "é" | ダブルクォートのみ。内部の"と\はエスケープする |
| number | 42, -3.14, 2.1e10 | 16進不可、NaN不可、先頭ゼロ不可 |
| boolean | true, false | 小文字のみ――Trueは無効 |
| null | null | 意図的に空であることを意味する。ゼロではない |
| object | {"key": "value"} | キーは文字列。末尾カンマは禁止 |
| array | [1, "two", null] | 順序は保持される。型の混在も可 |
エスケープ:文字列の中に住めるもの
文字列の中で、どこに現れても必ずエスケープしなければならない文字が2つあります。ダブルクォート(\"と書く)とバックスラッシュ(\\と書く)です。さらに制御文字用のエスケープが6つあります――\n改行、\tタブ、\r復帰、\bバックスペース、\fフォームフィード、そして\/がスラッシュ用。スラッシュのエスケープは有効ですが任意です。その他の文字は、UTF-8のままそのまま書けるほか、Unicodeコードポイントを\uXXXXエスケープで書くこともできます――どちらの表記も、パーサーにとってはまったく同じ文字列を意味します。
エスケープされた形
"path": "C:\\Users\\ada" "quote": "she said \"hi\"" "emoji": "\ud83d\ude00"
パーサーが渡してくるもの
path: C:\Users\ada quote: she said "hi" emoji: 😀
空白文字と整形、そして整形が存在する理由
構造を成す記号の間には、JSONが許す空白文字が厳密に4種類あります。スペース、タブ、改行、復帰です。この許容があるからこそ整形が可能になります。同じドキュメントが、通信路上では読めない1行になり、エディターの中ではインデントされたツリーになり、どちらもパーサーにはバイト単位でまったく同じデータです。整形は意味を何も変えません。だからこそフォーマッターツールはどんなペイロードにも安全に使え、転送には最小化したJSONが標準の選択になるのです。
- コメントはない:RFC 8259は、現実のパーサー間の実装の揺れを経て、コメントを意図的に削除しました。JSONCは、一部のツールが受け入れる非公式な拡張です。
- 末尾カンマはない:[1, 2, 3,] は、いかにも正しそうに見えても無効です。
- 重複キー:パーサーは最初か最後のどちらか一方を保持します――RFC 8259はこれを実装に委ねており、だからこそ、パースできたとしても重複キーはバグです。
- トップレベルは自由:どんな値でもドキュメント全体になり得ます――数値の配列だけで完全なJSONです。
JSONが使われる場所――使われない場所
JSONが治める領土は3つあります。APIのリクエスト・レスポンスのボディ、コメントがなくても困らない構造化設定、そしてドキュメントデータベースの中に置かれたデータです。通信路上では、2つの隣人と渋々同居しています。protobufのようなバイナリ形式――両端がスキーマを共有するときはサイズと速度で勝ります――と、運用設定の手編集で勝るYAMLです。したがってJSONを深く理解することは、数あるスキルのひとつではありません。あの2つの隣人を読むための前提条件です。YAML 1.2はJSONをパースでき、ほとんどのバイナリスキーマはJSONの例で自分自身を文書化しているのですから。
よくある質問
JSONは何の略ですか?
JavaScript Object Notationの略です。構文は2001年頃、Douglas CrockfordがJavaScriptのオブジェクトリテラルから切り出しましたが、形式そのものは言語中立です。RFC 8259は、どのプログラミング言語でも出力しパースできるテキスト形式として定めています。JavaScriptの機能ではなく、普遍的な交換形式になったのはこのためです。
JSONはプログラミング言語ですか?
いいえ――実行の意味論を持たないデータ形式です。ロジックも変数も関数も表現できず、表現するのは構造だけ。オブジェクト、配列、4つのスカラー型です。厳格さは意図的なものです。RFC 8259の文法はおおよそ1ページに収まり、あらゆる言語が同じように実装できたのはこの性質のおかげです。
JSONとJavaScriptオブジェクトの違いは何ですか?
目に見える違いは3つあります。JSONはキーにダブルクォートを要求し、末尾カンマを禁じ、undefined、関数、コメントを持たないこと。{name: 'ada'}のようなJavaScriptオブジェクトリテラルは有効なJSONではありません――{"name":"ada"}なら有効です。逆に、すべての有効なJSONドキュメントはJavaScriptオブジェクトとしてパースできます。2つがこれほど混同されるのはこのためです。
JSONでコメントが使えないのはなぜですか?
Douglas Crockfordが意図的に取り除きました。初期の形式交渉では、ベンダーがコメントの中へパース用の指令を詰め込み、相互運用性が壊れることが明らかになったからです。注釈が必要なら、"//"や"_comment"のような兄弟キーを置くのが慣習です。ツールチェーンが対応していればJSONCもあります――ただし、通信に載せるJSONは設計上、コメントなしのままです。
自分のJSONが有効かどうか確かめるには?
バリデーターに貼り付けてください。このサイトの「JSON検証」は、RFC 8259に従ってローカルでパースし、最初の構文エラーの正確な行と列を報告します。すべてブラウザ内での処理です。よくある失敗は、シングルクォート、末尾カンマ、クォートされていないキー、ワープロから貼り付いたスマートクォートです。
JSONのパースは安全ですか?
JSONテキストのパース自体は安全です。危険が残るのは、パーサーが渡してきたものを実行するときです。古典的な落とし穴が2つ。JavaScriptのJSON.parseの代わりにevalを使うこと(evalはコードを実行します)、そしてXMLの影響を受けたツールでの無制限のエンティティ展開です。ブラウザに搭載されているような標準準拠のパーサーは、深さとサイズに上限を設け、何も実行しません。