まえがき
プログラミングをしていると、JSONというものをよく目にします。
拡張子が.jsonでなにかの設定を書くファイルや、処理の中でJSON形式のデータを受け取ったりします。
しかし、「なんかJavaScriptのオブジェクトっぽいぞ?」と思ってみても、「なんか、配列のなかにオブジェクトが入ってるのとかもある...?([{},{}]のような)」という具合で、
一体なんなのよくわからず、その場しのぎでJSON.parseやらJSON.stringifyなどして扱っていました。
せっかくなので、調べて簡単にまとめたいと思います。
最初に結論
・異なるプログラミング言語間でデータをやりとりするための、共通のデータ記述形式。
・XMLに代わって、AJAX(非同期通信)やREST APIなどで使われるようになった。
・JavaScriptのオブジェクトを「由来」にしているし、実際、オブジェクトの形式で見かけることも多いが、配列や数値、Boolean単体で記述してもOKで、まったく別物。
・シングルクォートは使えず、ダブルクォートのみが使えて、オブジェクトのkeyは文字列に限るので、
{name: "John Smith", age: 33}
という書き方はダメで、正しくは、
{"name": "John Smith", "age": 33}
・JSON.stringify()でオブジェクトや値をJSON記法に変換、JSON.parse()で引数に渡された値をJSONとして解析して、オブジェクトや値に変換してくれる。
データ記述言語
JavaScript Object Notation(JSON、ジェイソン)はデータ記述言語の1つである。軽量なテキストベースのデータ交換用フォーマットでありプログラミング言語を問わず利用できる[1]。名称と構文はJavaScriptにおけるオブジェクトの表記法に由来する。
JavaScript Object Notation
https://ja.wikipedia.org/wiki/JavaScript_Object_Notation
「JSON とは」といったキーワードで調べると大体上のようなことが最初に書かれています。個人的にはWikipediaの説明が一番シンプルだと思いました。
でもこれ、シンプル過ぎて何言ってるのかよくわからないんですよね。わかる人にはわかる説明だと思うんですが、わからない人には、何を言ってんのかわからないという。
問題は、「データ記述言語」という言葉です。
「いやそりゃなんか書いてるんだし、表現しているのはデータなはずだから、'データ'を'記述'している言語だろそりゃ」(頭悪くてすみません)と思うのですが、これ、ちゃんとした用語なんですね。
データ記述言語(データきじゅつげんご)またはデータ言語とは、コンピュータにおいて扱うデータを記述するための形式言語である。コンピュータ言語の一種だが、プログラミング言語ではない。HTMLに代表されるマークアップ言語などがある。
データ記述言語
https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%BC%E3%82%BF%E8%A8%98%E8%BF%B0%E8%A8%80%E8%AA%9E
これをみると、「え、マークアップ言語がその一種? HTML?」という感じですが、
データ記述言語は、主にデータをテキストデータとして表現し記述するためのコンピューター用言語。プログラミング言語ではないが、プログラミングと関連が深い。
あるプログラミング言語によりメモリー上に表現されたデータ構造は、他のプロセスや他のプログラミング言語で扱うのに不便なので、汎用的な形式で書かれたデータを扱うようにすることが多い。具体的には、次節で挙げるような言語が存在する。
データ記述言語
https://enpedia.rxy.jp/wiki/%E3%83%87%E3%83%BC%E3%82%BF%E8%A8%98%E8%BF%B0%E8%A8%80%E8%AA%9E
と説明されていたり。
それで、また「JSON」に戻ると、
JavaScript だけではなく、Java, PHP, Ruby, Python など、様々な言語間のデータ交換、特に Ajax や REST API などで使用されています。
これまでは、共通データ定義言語として XML が利用されてきましたが、現在では、簡易的な JSON が利用されるケースが増えてきています。
JSONとは
http://www.tohoho-web.com/ex/json.html
と書かれていたり。
しかも、
他のデータ記述法との関係
XML
JSONはXMLと違ってマークアップ言語ではない。ウェブブラウザから利用できるという点では共通している。また両者とも巨大なバイナリデータを扱う仕組みがないことが共通している。
YAML
JSONはYAMLのサブセットと見なしてよい。YAMLにはブロック形式とインライン形式(フロー形式)の表記法があるが、JSONは後者にさらに制約を加えたものと捉えることができる。例えばRubyでは以下のようにしてJSONをYAMLとして読み込むことができる:
JavaScript Object Notation
https://ja.wikipedia.org/wiki/JavaScript_Object_Notation
と、XMLやYAMLと並べて説明されている。
ここで文系出身の私は、詳しいことはよくわからないが、なんとなく雰囲気で察しました。
要するに、異なるプログラミング言語間でデータをやりとりするための、共通のデータ記述形式であり、だからこそ、サーバーからデータを引っ張ってくる時や、逆にクライアントからサーバーにデータを渡す時に、一旦JSONに変換しているのではないかと。
そして、むかし(...いつ?)はXMLがその役割を担っていて、「AJAX」の'X'もXMLのことだったりする、つまりXML形式に変換してデータをやりとりしていたけど、最近ではもっぱらJSONという形式が使われるようになった。
結果的に、私のような末端でさえ、よくわからないけどJSONという形式のデータやファイルを頻繁に目にするようになったのだと。。。
詳しく説明するかと思いきや、雰囲気で察した結論となってしまいましたが、大体こんな感じではないでしょうか。
JavaScriptのオブジェクトじゃないの?
冒頭、
「なんかJavaScriptのオブジェクトっぽいぞ?」と思ってみても、「なんか、配列のなかにオブジェクトが入ってるのとかもある...?([{},{}]のような)」
と書きましたが、この辺に関しては、
JSONとは「JavaScriptのオブジェクト記法を用いたデータ交換フォーマット」です。
JSONとは?データフォーマット(データ形式)について学ぼう!
https://products.sint.co.jp/topsic/blog/json
と書かれていたりして、やっぱり混乱します。
Wikipediaには、
名称と構文はJavaScriptにおけるオブジェクトの表記法に由来する。
JavaScript Object Notation
https://ja.wikipedia.org/wiki/JavaScript_Object_Notation
と書かれています。
しかも、
JSONの型
JSON では下記の型を使用することができます。
文字列 ("...")
数値 (123, 12.3, 1.23e4 など)
ヌル値 (null)
真偽値 (true, false)
オブジェクト ({ ... })
配列 ([...])
JSON入門
http://www.tohoho-web.com/ex/json.html
ともあって、これはWikipediaにも同じ説明が。
またしても文系出身の私は察しました。
「これは、名前と書き方がJavaScriptのオブジェクトに「由来」しているだけで、まったく別物であり、配列でもいいんだ...!」
合ってますか?
ちなみに、JSONは「発見」されたみたいです。
ダグラス・クロックフォード(英語版)はJavaScriptのプログラマで、JSONを広めた一人だが、「The JSON Saga」と題したプレゼンテーション[4]中で「自分はJSONと名付けたが、考案者ではなく、それ自体は“自然に”存在していたもので、早い例としては1996年にはNetscape Navigatorでデータ交換用に使われていた。だから“発見した”ということになるのだが、発見したのも自分が最初ではない」といったように述べている。以上のことを縮めて「JavaScriptのオブジェクト表記法からJSONが発見された。」と表現されている場合がある。
JavaScript Object Notation
https://ja.wikipedia.org/wiki/JavaScript_Object_Notation
※ちなみに、「JavaScriptのオブジェクト記法を用いたデータ形式です」と書いてあって、記法にオブジェクトの例しか書いてないサイトもあったんですが、さすがにこれはミスリードでは...?
([{},{}]に関しては一切触れてなく、混乱します)
記法
Wikipediaから丸々引用させていただきます。
表記方法
JSONで表現するデータ型は以下の通りで、これらを組み合わせてデータを記述する[5]。true, false, null などは全て小文字でなくてはならない。
オブジェクト(順序づけされていないキーと値のペアの集まり。JSONでは連想配列と等価)
配列(データのシーケンス)
数値(整数、浮動小数点数)
文字列(バックスラッシュによるエスケープシーケンス記法を含む、ダブルクォーテーション"でくくった文字列)
真偽値(true と false)
null
数値は10進法表記に限り、8進、16進法表記などはできない。また浮動小数点数としては 1.0e-10 といった指数表記もできる。
文字列は(JSONそれ自体と同じく)Unicode文字列である。基本的にはJavaScriptの文字列リテラルと同様だが、囲むのにシングルクォートは使えない。バックスラッシュによるエスケープがある。
配列はゼロ個以上の値をコンマで区切って、角かっこでくくることで表現する。例えば以下のように表現する:
["milk", "bread", "eggs"]
オブジェクトはキーと値のペアをコロンで対にして、これらの対をコンマで区切ってゼロ個以上列挙し、全体を波かっこでくくることで表現する。例えば以下のように表現する:
{"name": "John Smith", "age": 33}
ここで注意することはキーとして使うデータ型は文字列に限ることである。したがって、
{name: "John Smith", age: 33}
という表記は許されない。この後者の表記はJavaScriptのオブジェクトの表記法としては正しいが、JSONとしては不正な表記である。
JavaScript Object Notation
https://ja.wikipedia.org/wiki/JavaScript_Object_Notation
なので、配列もOKなんですね。
だから、[{"aaa": "AAA"}, {"bbb": "BBB"}]もOKなんですね(「keyと値が文字列であるオブジェクトを要素に持つ、あくまで配列」)
ちなみに、
下記の様に、配列や値のみの表記も JSON に従ったデータとして認められます。
○ ["ABC", "DEF"]
○ "ABC"
○ 123
JSON入門
http://www.tohoho-web.com/ex/json.html
とのことで、やっぱり、「JavaScriptのオブジェクトと同じ記法です」というのは、ちょっと間違いで、「JavaScriptのオブジェクトの記法を由来にしているし、実際、オブジェクトの記法でよく見かけるが、結局別物」と考えてよいのだとおもいます。
ポイントとしては、
基本的にはJavaScriptの文字列リテラルと同様だが、囲むのにシングルクォートは使えない。
ここで注意することはキーとして使うデータ型は文字列に限ることである。したがって、
{name: "John Smith", age: 33}
という表記は許されない。
とあるように、シングルクォートは使えず、ダブルクォートのみが使えて、オブジェクトのkeyは文字列に限る、というのが点だとおもいます。
JSON.stringify JSON.parse
最後はなんとなく使っていたstringifyとparseです。MDNからコードも含めて引用させていただきます。
JSON.stringify() メソッドは、ある JavaScript のオブジェクトや値を JSON 文字列に変換します。置き換え関数を指定して値を置き換えたり、置き換え配列を指定して指定されたプロパティのみを含むようにしたりすることもできます。
JSON.stringify()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
console.log(JSON.stringify({ x: 5, y: 6 }));
// expected output: "{"x":5,"y":6}"
console.log(JSON.stringify([new Number(3), new String('false'), new Boolean(false)]));
// expected output: "[3,"false",false]"
console.log(JSON.stringify({ x: [10, undefined, function(){}, Symbol('')] }));
// expected output: "{"x":[10,null,null,null]}"
console.log(JSON.stringify(new Date(2006, 0, 2, 15, 4, 5)));
// expected output: ""2006-01-02T15:04:05.000Z""
JSON.stringify()は、オブジェクトや値を、よしなにJSON記法に変換してくれるんですね。
いままで、stringifyって、「文字列に直してんの?」「オブジェクトはJSON形式なのに、なんでstringifyする必要があるの?」とかおもったりしていました。
→(2020/12/28追記)「JSON記法にのっとった文字列」に直してるんですね。なので、あくまで文字列。
JSON.parse() メソッドは文字列を JSON として解析し、文字列によって記述されている JavaScript の値やオブジェクトを構築します。任意の reviver 関数で、生成されたオブジェクトが返される前に変換を実行することができます。
JSON.parse()
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
const json = '{"result":true, "count":42}';
const obj = JSON.parse(json);
console.log(obj.count);
// expected output: 42
console.log(obj.result);
// expected output: true
逆に、JSON.parse()は、渡された引数をJSONとして解析して、オブジェクトや値に変換してくれるんですね。
残った疑問
最後に引用したMDNの記事、JSON.parseに渡すJSON文字列にシングルクォート入ってるし('{"result":true, "count":42}')、JSON.stringifyの方では、オブジェクト自体がダブルクォーテーションで囲まれている("{"x":5,"y":6}")...?
[2021/03/31追記]
こちら前者はJSON.parse()の引数は文字列、JSON.stringify()の戻り値は文字列、だったことからでした。
@towa_skm さんにコメント欄にて教えていただきました。
あとがき
だいぶ正確性を疎かにした記事ですが、どうでしょうか。
自分ではどれくらい合ってるのかよくわかりませんが、理解のために、まとめてみました。