JSONとは何か?構文ルールと6つのデータ型から、末尾カンマなどよくあるエラーの直し方まで実例で徹底解説
JSONとは、テキストだけでデータの構造を表現するための軽量なフォーマットです。JavaScript Object Notationの略で、オブジェクトと配列を入れ子にして値を表現でき、プログラミング言語を問わずAPIのレスポンスや設定ファイル、ログの保存に使われています。構文はシンプルですが、いくつかの厳格なルールがあり、そこから外れると即座にパースエラーになります。
JSONの正体
JSONで表現できる値の種類は6つしかありません。
- 文字列(ダブルクォートで囲んだものだけが有効)
- 数値
- 真偽値(
true/false) null- オブジェクト(
{}) - 配列(
[])
これだけです。日付型も関数もSetもMapも存在せず、この6種類の組み合わせだけですべてのデータを表現します。
構文のルールも数えるほどしかありませんが、どれも例外を許しません。
- オブジェクトのキーは必ずダブルクォートで囲んだ文字列にする
- 配列やオブジェクトの最後の要素の後ろにカンマを置かない(末尾カンマ禁止)
- コメントは一切書けない
- 文字列やキーはダブルクォートのみで囲む。シングルクォートは使えない
- キーを引用符なしで書くことはできない
NaN、Infinity、undefinedはJSONの値として認められない- 関数はJSONで表現できない
これらのルールは「読みやすさのための推奨事項」ではなく、パーサーがエラーを返すかどうかを分ける絶対的な条件です。次の章で、これがJavaScriptのオブジェクトリテラルとどう違うのかを見ていきます。
JSONとJavaScriptのオブジェクトリテラルの違い
JSONの見た目はJavaScriptのオブジェクトリテラルとほぼ同じなので、JavaScriptを書き慣れたエンジニアほど「JSONもオブジェクトリテラルと同じ書き方でいいはず」と思い込みやすい部分です。しかしJSONはJavaScriptの構文の一部を借りているだけの、独立したデータフォーマットです。実際に許される書き方には次のような違いがあります。
| 項目 | JSON | JavaScriptのオブジェクトリテラル |
|---|---|---|
| キーの引用符 | 必須(ダブルクォートのみ) | 不要(省略可能) |
| 末尾カンマ | 不可 | 可 |
| コメント | 不可 | 可 |
| シングルクォートの文字列 | 不可 | 可 |
| 値として関数を書く | 不可 | 可 |
値としてundefinedを書く | 不可 | 可 |
JavaScriptのコード内で const config = { name: 'ada', debug: true, } のようなオブジェクトリテラルを書くのは何の問題もありません。キーの引用符は省略でき、末尾のカンマも許され、シングルクォートの文字列も使えます。ところがこの同じ文字列をJSON.parseに渡すと、キーが引用符なしであること、シングルクォートを使っていること、末尾にカンマが残っていることの3点すべてで弾かれます。JSONはJavaScriptの構文を土台にしているだけで、パーサーが受け入れる範囲はJavaScriptよりずっと狭い、別物の仕様です。
実践例:実際のAPIレスポンスを圧縮・整形する
APIがネットワーク越しに返してくるJSONは、たいてい空白も改行もない圧縮された1行です。次のオブジェクトを例に、圧縮した形と整形した形を比べてみます。
圧縮版(空白なし、ちょうど107文字)。
{"id":1,"name":"Ada Lovelace","email":"[email protected]","roles":["admin","user"],"active":true,"meta":null}
同じデータをインデント2スペースで整形すると、次の145文字になります。
{
"id": 1,
"name": "Ada Lovelace",
"email": "[email protected]",
"roles": [
"admin",
"user"
],
"active": true,
"meta": null
}
145文字は107文字よりおよそ35%大きく、その差はすべて追加されたスペースと改行だけが原因です。データの中身は1バイトも変わっていません。APIが圧縮版を送ってくるのは、このスペースと改行の分だけ転送量を減らせるからです。ネットワークを流れる間は圧縮されたままの方が効率がよく、人間が読むときだけ整形すれば十分だという考え方です。ログに出力されたレスポンスを目で追ったり、ネストしたオブジェクトや配列の対応関係を確認したりする作業は、圧縮版のままでは現実的ではありません。
自分のJSONを整形する
手元のJSONを貼り付けて、整形と検証をその場で試せます。
よくある間違いとエッジケース
末尾カンマ。 {"id":1,"name":"Ada",} のように最後のプロパティの後ろにカンマを残すと、V8(ChromeやNode.jsが使うJavaScriptエンジン)は次のエラーを返します。
Expected double-quoted property name in JSON at position 21 (line 1 column 22)
エラー文が「ダブルクォートで囲まれたプロパティ名を期待していた」と言っているのは、パーサーがカンマの直後に次のキーが続くと想定しているのに、実際には}しか出てこなかったためです。
キーに引用符がない、またはシングルクォートを使っている。 {id:1} のようにキーを引用符なしで書くと、次のエラーになります。
Expected property name or '}' in JSON at position 1 (line 1 column 2)
{'a':1} のようにシングルクォートでキーを囲んだ場合も、同じ種類のエラーになります。
Expected property name or '}' in JSON at position 1 (line 1 column 2)
パーサーから見れば、引用符がないこととシングルクォートを使っていることは区別されず、どちらも「有効なプロパティ名として認識できない文字」として同じ扱いになります。
NaNやundefinedを値に使う。 {"a":NaN} は次のエラーになります。
Unexpected token 'N', "{"a":NaN}" is not valid JSON
{"a":undefined} も同様に弾かれます。
Unexpected token 'u', "{"a":undefined}" is not valid JSON
NaNとundefinedはどちらもJavaScriptの中では正当な値ですが、JSONの6つの値の型には含まれていません。数値が存在しないことを表したいときは、代わりにnullを使います。
なお、これらのエラーメッセージの文言はV8(ほとんどの訪問者のブラウザでJSON.parseを実行しているエンジン)のものです。Firefoxが使うSpiderMonkeyエンジンなど、他のJavaScriptエンジンでは文言の細部が異なる場合がありますが、パースが失敗するという結果自体は変わりません。
重複したキーが静かに上書きされる。 {"a":1,"a":2} は構文としては完全に有効で、エラーは一切出ずにパースが成功し、結果は {"a":2} になります。JavaScriptを含むほとんどのパーサーは、同じキーが複数回出てきた場合、後に書かれた値だけを採用し、それより前の値を黙って捨てます。これは実務でありがちなバグの温床です。たとえばビルドツールが生成した設定ファイルや、手作業で編集したJSONに同じキーが2回紛れ込んでいても、パースはエラーなく通ってしまうため、意図した方の値が上書きされていることに誰も気づかないまま本番に出ていく、ということが起こり得ます。
よくある質問
JSONとは何ですか。
JSONとは、文字列・数値・真偽値・null・オブジェクト・配列という6つの値の型を使ってデータ構造を表現する軽量なテキストフォーマットです。プログラミング言語を問わず読み書きでき、APIのレスポンスや設定ファイルの保存によく使われます。
JSONはJavaScriptのオブジェクトと同じものですか。
見た目はよく似ていますが同じではありません。JSONはキーを必ずダブルクォートで囲む必要があり、末尾カンマやコメント、シングルクォートの文字列、関数、undefinedを値にすることは一切許されません。JavaScriptのオブジェクトリテラルはこれらすべてが可能なので、JSONの方がずっと制約の厳しい仕様だと考えてください。
末尾にカンマがあるとなぜJSONが壊れるのですか。
JSONの仕様が末尾カンマを明示的に禁止しているためです。{"id":1,"name":"Ada",} のように最後のプロパティの後にカンマを残すと、パーサーはカンマの後に次のプロパティ名が続くと期待するため、Expected double-quoted property name in JSON at position 21 (line 1 column 22) というエラーで止まります。
JSONにコメントは書けますか。
書けません。JSONの仕様にコメントの構文自体が存在しないため、//や/* */をJSONファイルに書くとパースエラーになります。設定に説明を残したい場合は、コメント可能なYAMLなど別のフォーマットを検討するか、JSONの構造自体にドキュメント用のキーを追加する方法があります。
オンラインの整形ツールを使うと、データはサーバーに送信されますか。
このツールに関しては送信されません。pluri.toolsのJSONフォーマッターはJSON.parseとJSON.stringifyをブラウザ内のJavaScriptだけで実行しており、ネットワーク越しのfetch処理は一切発生しません。貼り付けたJSONがその端末の外に出ることはないので、機密情報を含むデータでも安心して整形・検証に使えます。