# JSON

JSON|  |
| 拡張子 |
.json |
| MIMEタイプ |
application/json |
| 種別 |
Data interchange |
| 国際標準 |
IETF STD 90 RFC 8259 ECMA-404 2nd edition ISO/IEC 21778:2017 |

**JSON**（ジェイソン、**JavaScript Object Notation**）はデータ記述言語の1つである。軽量なテキストベースのデータ交換用フォーマットでありプログラミング言語を問わず利用できる。名称と構文はJavaScriptにおけるオブジェクトの表記法に由来する。

## 特徴

JSONはウェブブラウザなどでよく使われているECMA-262, revision 3準拠のJavaScript (ECMAScript) をベースとしている。2006年7月にRFC 4627で仕様が規定され、その後、何度か改定され、2017年12月14日にIETF STD 90およびRFC 8259およびECMA-404 2nd editionが発表された。MIMEタイプは `application/json`、拡張子はjsonとされた。

IETFおよびECMAおよびISOの仕様の改定の歴史

* 2006年7月 - RFC 4627
* 2013年3月 - RFC 7158
* 2013年10月 - ECMA-404 1st edition
* 2014年3月 - RFC 7159
* 2017年11月30日 - ISO/IEC 21778:2017
* 2017年12月14日 - RFC 8259 および IETF STD 90 および ECMA-404 2nd edition

JSONはJavaScriptにおけるオブジェクト表記法のサブセットであるが、JavaScript以外の言語でも読み込み・書き込みが提供されている。そのため、ウェブアプリケーションでのサーバとクライアントの間でのデータの受渡しなど、プログラミング言語が異なるプログラミング言語同士での通信でよく使われる。

JavaScriptでJSONを読み込むには、文字列をJavaScriptのコードとして解釈する `eval` 関数を使うだけでよい。JSONの登場当時は、広く普及した言語であるJavaScriptで簡単に読み込めるため、開発者達から注目を浴びた。現在では`eval` にはセキュリティ上の問題があるため、専用の`JSON.parse` 関数を使うべきである。

### JSONの発見

ダグラス・クロックフォードはJavaScriptのプログラマで、JSONを広めた一人だが、「The JSON Saga」と題したプレゼンテーション中で「自分はJSONと名付けたが、考案者ではなく、それ自体は“自然に”存在していたもので、早い例としては1996年にはNetscape Navigatorでデータ交換用に使われていた。だから“発見した”ということになるのだが、発見したのも自分が最初ではない」といったように述べている。以上のことを縮めて「JavaScriptのオブジェクト表記法からJSONが発見された。」と表現されている場合がある。

## 表記方法

JSONで表現するデータ型は以下の通りで、これらを組み合わせてデータを記述する。`true`, `false`, `null` などは全て小文字でなくてはならない。

* オブジェクト（順序づけされていないキーと値のペアの集まり。JSONでは連想配列と等価）
* 配列（データのシーケンス）
* 数値（整数、浮動小数点数）
* 文字列（バックスラッシュによるエスケープシーケンス記法を含む、ダブルクォーテーション`"`でくくった文字列）
* 真偽値（`true` と `false`）
* `null`

数値は10進法表記に限り、8進、16進法表記などはできない。また浮動小数点数としては `1.0e-10` といった指数表記もできる。精度にかかる仕様や要求はなく、表記された値の取扱精度は実装に依存する。無限大およびNaNの表記はできない。

文字列は（JSONそれ自体と同じく）Unicode文字列である。基本的にはJavaScriptの文字列リテラルと同様だが、囲むのにシングルクォートは使えない。バックスラッシュによるエスケープがある。

配列はゼロ個以上の値をコンマで区切って、角かっこでくくることで表現する。例えば以下のように表現する：

```
["milk", "bread", "eggs"]

```

オブジェクトはキーと値のペアをコロンで対にして、これらの対をコンマで区切ってゼロ個以上列挙し、全体を波かっこでくくることで表現する。例えば以下のように表現する：

```
{"name": "John Smith", "age": 33}

```

ここで注意することはキーとして使うデータ型は文字列に限ることである。したがって、

```
{name: "John Smith", age: 33}

```

という表記は許されない。この後者の表記はJavaScriptのオブジェクトの表記法としては正しいが、JSONとしては不正な表記である。

プログラム上で生成した文字列をJSONとして扱う場合、ダブルクォーテーション`"`を含む文字列を利用しなければいけないことに注意が必要である。なぜならコード上の`"`は文字列定義に利用される`"`であり、生成されるのはあくまで文字列`hello`であって文字列`"hello"`ではない。JSONの文字列型は後者であると定義されているので、以下のようにエラーを発生させる。利用時にはJSON生成関数（例 JavaScript: `JSON.stringify`）を利用する方がより安全である。

```
const invalidJSON = "hello";
const validJSON = '"hello"';

JSON.parse(invalidJSON)
// Thrown:
// SyntaxError: Unexpected token h in JSON at position 0
JSON.parse(validJSON)
// 'hello'

// safe JSON generation
const output = JSON.stringify("hello")
output
// '"hello"'

```

### エンコーディング

RFC 8259より、閉じられたエコシステムで利用する場合を除き、文字コードはUTF-8でエンコードすることが必須 (MUST) となっている。ネットワークでJSONを送信する場合は、バイト順マークを先頭に付加してはいけない (MUST NOT)。

過去のIETFの仕様では、JSONテキストはUnicodeでエンコードするとされていた (SHALL)。デフォルトのエンコーディングはUTF-8であった。なお、単独の文字列でない限り最初の2文字は必ずASCII文字であるので、最初の4バイトを見ることにより、UTF-8、UTF-16LE、UTF-16BE、UTF-32LE、UTF-32BEのいずれの形式でエンコードされているか判別できた。

## AjaxにおけるJSONの利用

AjaxにおいてXMLHttpRequestで非同期にJSONでのデータを受け取る例を示す：

### 古典的な例

```
var the\_object;
var http\_request = new XMLHttpRequest();
http\_request.open( "GET", url, true );
http\_request.onreadystatechange = function () {
 if ( http\_request.readyState == 4 ) {
 if ( http\_request.status == 200 ) {
 the\_object = eval( "(" + http\_request.responseText + ")" );
 } else {
 alert( "There was a problem with the URL." );
 }
 http\_request = null;
 }
};
http\_request.send(null);

```

### 新しい記法を利用した例

```
var the\_object;
var http\_request = new XMLHttpRequest();
http\_request.open( "GET", url, true );
http\_request.responseType = "json";
http\_request.addEventListener ( "load", function ( ev ) {
 if ( ev.target.status == 200 ) {
 the\_object = http\_request.response;
 } else {
 alert( "There was a problem with the URL." );
 }
 delete http\_request;
});
http\_request.send(null);

```

ここでいずれも、`http_request` はXMLHttpRequestオブジェクトであり、それを `url` にアクセスして返ってきたJSONで記述されたデータを `the_object` に格納される。いま、XMLHttpRequestを用いて実装をしたが、iframeなどの他の実装方法もある。また、JavaScriptライブラリのprototype.jsではHTTPの `X-JSON` ヘッダを利用して簡単にJSONデータの受渡しができる。

## ライブラリ

JSONは多くのプログラミング言語で利用可能なライブラリなどが提供されている。例えば、ActionScript, C, C++, C#, ColdFusion, Common Lisp, Curl, D, Delphi, E, Elixir, Erlang, Groovy, Haskell, Java, JavaScript (ECMAScript), Lisp, Lua, ML, Objective-C, Objective CAML, Perl, PHP, Python, R, Rebol, Ruby, Scala, Squeakなど。

ただし、テキストファイル、データを交換する手段を持つプログラミング言語であれば自力でパースして入力したり、フォーマット処理で出力は可能である。

## JSONPath

JSONPath は JSON のクエリ式で、JSON の一部分を示すことが出来る。XML の XPath に対応するものとして Stefan Gössner が2007年に提案し、2024年2月にRFC 9535として仕様が制定された。様々なプログラミング言語でライブラリが実装されている。データベースでは、Oracle Database、Microsoft SQL Server、MySQL、PostgreSQL、MongoDB、RedisJSONなど広く採用されている。

例として、下記 JSON に対する、`$.users[0:2].name` の結果は `["Foo", "Bar"]` になる。

```
{
 "users": [
 {"name": "Foo"},
 {"name": "Bar"},
 {"name": "Baz"}
 ]
}

```

## 改行区切りのJSON

1行を1つのJSONとする改行区切りのJSONが複数の人によって提案されている。仕様は同一である。改行コードは \n を使わなければならないが、JSON の末尾に \r があっても無視されることから \r\n も利用可能である。

* JSON Lines (JSONL) - 拡張子は .jsonl 、MIMEタイプは application/jsonl
* Newline delimited JSON (NDJSON)（旧称 Line delimited JSON, LDJSON）- 拡張子は .ndjson 、MIMEタイプは application/x-ndjson

Comma-Separated Values よりも柔軟性がある。また、JSONの配列を使うよりも可読性があるうえ、ストリーミングにすることができる。以下は例。

```
{"ts":"2020-06-18T10:44:12","started":{"pid":45678}}
{"ts":"2020-06-18T10:44:13","logged\_in":{"username":"foo"},"connection":{"addr":"1.2.3.4","port":5678}}
{"ts":"2020-06-18T10:44:15","registered":{"username":"bar","email":"bar@example.com"},"connection":{"addr":"2.3.4.5","port":6789}}
{"ts":"2020-06-18T10:44:16","logged\_out":{"username":"foo"},"connection":{"addr":"1.2.3.4","port":5678}}

```

## JSON5

ECMAScript 5.1 に基づき、人間にとってより読み書きしやすい JSON5 が提案されている。コメントを書けたり、オブジェクトのキーは " が不要だったり、末尾カンマを付けられたりする。拡張子は .json5 、MIMEタイプは application/json5 。

```
// コメント
{a: 1,}

```

## 他のデータ記述法との関係

XML
JSONはXMLと違ってマークアップ言語ではない。ウェブブラウザから利用できるという点では共通している。また両者とも巨大なバイナリデータを扱う仕組みがないことが共通している。
YAML
JSONはYAMLのサブセットと見なしてよい。YAMLにはブロック形式とインライン形式（フロー形式）の表記法があるが、JSONは後者にさらに制約を加えたものと捉えることができる。例えばRubyでは以下のようにしてJSONをYAMLとして読み込むことができる：

```
the\_object = YAML.load('{"name": "John Smith", "age": 33}')

```

YAML 1.1以前は、配列と連想配列の区切りをそれぞれ `,`  のようにカンマ+スペースの形にすることでJSONのスーパーセットとなったが、YAML 1.2では区切り文字も互換となったため、正常なJSON文書においては公式に完全なスーパーセットとなった。僅かな相違点として、連想配列のキーがユニークであるべきことをJSONではSHOULDレベルで要請するのに対し、YAML 1.2ではMUSTレベルで要請している為、該当する異常データのエラーハンドリングに違いが出る可能性はある。

* Ajax
* JSONP
* JSON Schema
* JSON-RPC
* JSON Web Token
* Jaql
* MooTools
* コンピュータ言語

* Introducing JSON （英語）
	+ JSONの紹介 （日本語）
* IETFの仕様書
	+ IETF STD 90 および RFC 8259
	+ 古い廃止された仕様書
		- RFC 4627 （英語）
		- RFC 7158 （英語）
		- RFC 7159 （英語）
* ECMA-404 （英語）
* ISO/IEC 21778:2017 （英語）