どうも。つじけ(tsujikenzo)です。このシリーズでは、JSONについて、全3回でお送りします。(2021年11月に大幅にリニューアルしました)
はじめに
JSONは、JavaScript Object Notationの略です。
2006年に、Douglas Crockford氏が、JavaScriptからデータ構造を発見したのが、JSONと言われています。
JSONは、JavaScriptと関係があるようですが、いまいちつかみどころがない感じです。
なので、このブログでは、ノンプログラマーのわたしでも理解できるように、JSONを噛み砕いてみました。
今日のアジェンダ
- JSONの誕生
- JSONの仕様
- parserも理解してしまおう
JSONの誕生
インターネットのさまざまな仕様を定めているRFC(Request for Comments)の、第4627は、JSONにとって最初の仕様書です。
仕様書の概要(Abstract)は、Crockford氏によってこう書かれています。
JSONは、軽量でテキストベースの、言語に依存しないデータ交換形式です。
JSONは、ECMAScriptプログラミング言語標準から派生しました。
JSONは、構造化データの移植可能な表現のためのフォーマットルールの小さなセットを定義します。
https://www.ietf.org/rfc/rfc4627
当時、米Yahoo!で、ゴリゴリのJavaScriptエンジニアだったCrockford氏は、「JavaScriptのオブジェクトって、データのやり取りをするのに便利なんじゃね?」と思いました。
「思った」というのは乱暴な言い方ですが、彼は「世界中のエンジニアが、データをやりとりするために書いてる、このJavaScriptのオブジェクトの書き方、使い方って、共通化できるんじゃないかな」という発見をしたそうです。
そこで、「いろいろなルールを決めて、JSONって名前をつけました。みなさまからのコメントをお待ちしています」というのが、RFC4627です。
JSONの仕様
JSONの、最終的な仕様書であるRFC8259では、以下のように書かれています。
JavaScriptのオブジェクトリテラルから派生しています
JavaScript Object Notation(JSON)は、軽量でテキストベースの言語に依存しないデータ交換形式
JSONは、4つのプリミティブ型(文字列、数値、ブール値、ヌル(null))と2つの構造化型(オブジェクトと配列)を表すことができます
http://www.asahi-net.or.jp/~ax2s-kmtn/internet/rfc8259j.html
まずは、JSONがオブジェクトリテラルから派生していること、テキストベースであることに触れてみたいと思います。
オブジェクトリテラル
以前、ブログで、オブジェクトリテラルについてまとめました。
JavaScriptでは、以下のルールにしたがって記述すると、それはオブジェクトであると定義されます。
- オブジェクトは必ず波カッコ{}で囲まれており、
- プロパティ(1つ1つの要素)はkey:value形式、
- 複数のプロパティがある時はカンマ区切りで記述する
const person = { id: 'tg001', name: 'つじけ', age: 35, favorite: 'Coffee' };
console.log(typeof person); //object
また、オブジェクトの一部である、配列も、JSONで取り扱いできます。
配列は、以下のルールにしたがって記述すると、それは配列であると定義されます。
- 配列は必ず角カッコ[]で囲まれており、
- 複数のプロパティがある時はカンマ区切りで記述する
const array = [1,2,3];
console.log(Array.isArray(array); //true
JavaScriptには、ほかにも、Map型やSet型といったオブジェクトの型がありますが、JSONで取り扱いできるのは、オブジェクトと配列の2種類のみです。
JSONはテキストベース
JSONは、テキストベースです。
リテラルにJSONを生成しようとしたばあいは、前述した、オブジェクトか配列を文字列にする必要があります。
なので、値を文字列にする必要があります。
注意が必要なことは、オブジェクトのばあいは、中身をダブルクォーテーションで囲まないといけない点です。
//このままではJSONとして処理できない1
const person = { id: 'tg001', name: 'つじけ', age: 35, favorite: 'Coffee' };
// console.log(JSON.parse(person)); //SyntaxError: Unexpected token o in JSON at position 1
//このままではJSONとして処理できない2
const array = [1, 2, 3];
// console.log(JSON.parse(array)); //SyntaxError: Unexpected token , in JSON at position 1
//文字列化してJSONとして操作する(オブジェクトの中は、必ずダブルクォーテーション)
const textPerson = '{ "id": "tg001", "name": "つじけ", "age": 35, "favorite": "Coffee" }';
const textArray = '[1, 2, 3]';
console.log(JSON.parse(textPerson)); //{ id: 'tg001', name: 'つじけ', age: 35, favorite: 'Coffee' }
console.log(JSON.parse(textArray)); // [ 1, 2, 3 ]
この、文字列にする処理ですが、単に両端をシングルクォーテーションやバックティックで囲めばいいのですが、ダブルクォーテーションのルールもあるので、タイプミスする可能性があります。
確実な方法は、JSON.stringify()メソッドを使うことです。
//このままではJSONとして処理できない1
const person = { id: 'tg001', name: 'つじけ', age: 35, favorite: 'Coffee' };
const array = [1, 2, 3];
//オブジェクトや配列を文字列化する
const textPerson = JSON.stringify(person);
const textArray = JSON.stringify(array);
console.log(JSON.parse(textPerson)); //{ id: 'tg001', name: 'つじけ', age: 35, favorite: 'Coffee' }
console.log(JSON.parse(textArray)); // [ 1, 2, 3 ]
テキストベースは便利なフォーマット
JSONのように、とあるデータをテキストとしてやり取りする仕組みに、ご存知CSVがあります。
CSVは、Comma-Separated Valuesの略で、データをカンマで区切りましょうというルールです。
Excelにこのような表があった時、
name | age | favorite |
---|---|---|
Tom | 20 | Coffee |
Bob | 25 | Apple |
CSVで出力すると、このようなデータになっているのを目にしたことがありますよね。
name,age,favorite
Tom,20,Coffee
Bob,25,Apple
Excelと他のソフトでやり取りするのに、CSVというテキストデータに変換してやりとりをすると、とても便利だねというお話です。
XMLもテキストデータ
せっかくなので、XMLも覚えてしまいましょう。JSON、CSV、XMLは3大テキストデータです。
XMLの正式名称は、Extensible Markup Languageです。
HTML(HyperText Markup Language)と見比べると、Markup Languageのところが一緒ですよね。
タグで囲まれていて、タグの中にタグをいれて入れ子に表現できるのがXMLの特徴です。
さきほどのCSVの表を、XMLで表現するとこうなります。
<?xml version='1.0' encoding='utf-8'>
<root>
<employee>
<employ>
<name>Tom</name>
<age>20</age>
<favorite>Coffee</favorite>
</employ>
<employ>
<name>Bob</name>
<age>25</age>
<favorite>Apple</favorite>
</employ>
</employee>
</root
JSON、CSV、XMLの、それぞれ記述方式のルールは違いますが、テキストデータでやり取りする、という考え方は共通しています。
parser(パーサー)も理解してしまおう
JSON、CSV、XMLが、単なるテキストデータということが理解できました。
テキストデータを解析(パースする)するのは、parser(パーサー)のお仕事です。
たとえば、JSONはキーバリュー方式、CSVはカンマ区切り、XMLはタグの入れ子構造、というルールがあるなら、「○○というテキストデータがあった時、それはどの形式ですか?」という判定するのもかんたんです。
その判定をするための道具が、**parser(パーサー)**です。
JSON.parse()メソッド
組み込みオブジェクトの、JSONオブジェクトには、JSON.parse()メソッドが提供されています。
これは、文字列をJSONとして解析して、Object, Array, 文字列, 数値, 論理値, null 値のいずれかで返すメソッドです。(何を返すのかは、指定されたJSONのtextに対応する値です)
const person = { id: 'tg001', name: 'つじけ', age: 35, favorite: 'Coffee' };
const array = [1, 2, 3];
//オブジェクトや配列を文字列化する
const textPerson = JSON.stringify(person);
const textArray = JSON.stringify(array);
console.log(typeof textPerson, typeof textArray); //string string
//JSONをJSONオブジェクトに変換する
console.log(JSON.parse(textPerson)); //{ id: 'tg001', name: 'つじけ', age: 35, favorite: 'Coffee' }
console.log(JSON.parse(textArray)); // [ 1, 2, 3 ]
console.log(typeof JSON.parse(textPerson),typeof JSON.parse(textArray)); //object object
まとめ
以上で、【基礎前編】JSONとは何か、をお届けしました。
「JSONはテキストデータ」というポイントが大事です。
次回は、【基礎後編】4つのプリミティブ型と2つの構造化型をお届けします。