Comments
Description
Transcript
JSON
JSON について JSON (JavaScript Object Notation)は、XML などと同様のテキストベースのデータフォーマ ットである。その名前の由来の通り JSON は JavaScript のオブジェクト表記構文のサブセッ トとなっており、XML と比べると読み書きが容易で、人間が理解しやすいデータフォーマッ トと言える。マシンにとっても簡単にパース(一定の書式や文法に従って記述されたデータ を解析し、プログラムで扱えるようなデータ構造の集合体に変換すること )や生成を行なえ る形式である。 JavaScript プログラミング言語 (ECMA-262 標準第 3 版 1999 年 12 月)の一 部をベースに作られている。 JSON は完全に言語から独立したテキスト形式だが、C、C+ +、C#、Java、JavaScript、Perl、Python、その他多くの C ファミリーの言語を使用するプログラマ にとっては、馴染み深い規約が使われている。これらの性質が、JSON を理想的なデータ交換 言 語 に し て い る 。 な お 、 JSON は 2006 年 に 「 RFC 4627 ( http://www.rfceditor.org/rfc/rfc4627.txt)」として公開されている。他言語で扱う場合でも、XML と比べて比 較的仕様が簡単なので、導入が容易であろう。 例として XML と JSON で同じデータを記述したものをリスト 1 とリスト 2 に示す(図 1)。 リスト 1 の XML ではすべての情報をタグで囲んだテキストノードとして記述して いるが 、 XML でデータを表現する場合、データの記述方法として属性とテキストノードの使い分け が必要になる。 JSON の場合、そのようなことを気にする必要はない。また、XML には閉じタグが必要とな るが、JSON の場合カッコに対応する閉じカッコ以外は不要である。JSON は XML と比べる とタイプ数も少なく、きちんとインデント(字下げ)されていれば可読性も高いことがわかる。 リスト1:XML の例 リスト2:JSON の例 <employees> <employee> <empld>000001</empld> <department>企画部 </department> <name>山田太郎</name> <employee> <employee> <empld>000002</empld> <department>営業部 </department> <name>山田次郎</name> [ { "empld":"000001", "deprtment":"企画部", "name":"山田太郎", }, { } "empld":"000002", "deprtment":"営業部", "name":"山田次郎", ] XMLHttpRequest で非同期通信 サーバ ど) Web ブラウ ザ XML XML を返却 受け取った XML を使用し、DHTML を 駆使して Web ブラウザ内のコンテンツ を書き換える 図1:同データの XML と JSON の記述例と Ajax の概念図 処理速度 json は XML よりは高速であると言える。これは XML がデータの区切りを判定する要素(開始 タグ・終了タグ)の名前を自由に決められるのに対して、JSON はデータの区切りは角かっ こ”[]”・波かっこ”{}”・コロン”:”・ダブルクォーテーションの各 1 バイトで固定的に仕様化 しているので構文解析処理を高速化できる事が理由である。 JSON の利用シーン JSON は前述の通り、JavaScript のサブセットなので eval()関数で評価することで JavaScript オブジェクトに変換することができるという特徴があ る。eval()関数は引数で渡された文字 列を JavaScript コードとして評価し、その結果を返す。 このように JavaScript との親和性の高さから現在では Ajax でのデータ交換フォーマットと して広く利用されるようになった。 Ajax はもともと Asynchronous JavaScript + XML の略で、 Web ブラウザ上で動作する JavaScript でサーバから XML データを取得し、取得したデータを DHTML を活用してコンテ ンツに動的に反映するという手法である(図 1)。 この XML の代わりに JSON が使われているわけである。JSON を利用することで冗長な XML と比べて通信時のデータ量を削減できるなどのメリットもある。 Ajax のサーバサイドは Java や PHP などの言語を利用して実装されることが多いが、すで に主要なプログラミング言語には JSON の生成や読み込みを行うライブラリが存在するた め、JavaScript に限らず言語をこえたデータ交換のためのデータフォーマットとして JSON を利用することができる。 JSON の構造 JSON は 2 つの構造を基にしている。 名前/値のペアの集まり。様々な言語で、これはオブジェクト、レコード、構造体、ディ クショナリ、ハッシュテーブル、キーのあるリスト、連想配列として実現されている。 値の順序付きリスト。ほとんどの言語で、これは配列として実現されている。 JSON では、以下の形式を持っている。 「オブジェクト」は{}で全体を囲み、キーと値のペアをコロン(:)で区切って記述する。カン マ(,)で複数のキーと値を記述することも可能である。キーには文字列のみ使用可能であ る。オブジェクトの記述例を以下に示す。 { 文字列:値, 文字列:値, . . 文字列:値 } 例 { "name":"Taro Yamada", "age":22 } 「配列」は繰り返し項目を表現する際に使用する。大括弧([ , ])で囲み、中の要素を値の連続 (0 個以上)で表現する。複数の要素を利用する場合は、カンマで区切り、続けて記述する。 配列の記述例を以下に示す。 [ 値, 値, ..., 値] 例 ["JavaScript","Ajax","JSON"] 構造化されたデータを表現するために、値はオブジェクトや配列も含まれているので、オブ ジェクトと配列を自由にネストさせることができる。オブジェクトと配列をネストさせた 場合の記述例をする。 例 person.json [ { "name":"son", "age":21, "hobby":["baseball","car"] }, { "name":"daughter", "age":18, "hobby":["shopping","tv game"] }, { "name":"daddy", "age":42, "hobby":["car","fishing"] } ] この JSON ファイルの構造は、個人情報をオブジェクト単位として複数人分用意し配列とし ている。個人情報は、名前・年齢・趣味がある。名前は文字列、年齢は数値、趣味は複数ある ので配列としている。配列の中は文字列としている。 JSON で利用可能なデータ型 続いて JSON で利用可能なデータ型について説明する。 JSON では「数値(number) 」 「文字列(string) 」 「配列(array) 」 「オブジェクト(object) 」 「論理値 (true、false)」「null」のデータ型を利用することができる。 数値(number) 数値は 10 進数で表記する。8 進数や 16 進数は使用できない。 多くのプログラミング言語と 同様、整数および小数部、指数部の記述が可能である。負数を表すにはマイナス記号 ( - ) を 付けるが、正数を表すのにプラス記号 ( + ) は使用できない。 文字列 (string) JavaScript では文字列を記述するのに、ダブルクォート ( " ) かシングルクォート ( ' ) のいず れかを使用できる。しかし JSON では、ダブルクォートしか認められないことに注意が必要 である。使用可能な文字は、ダブルクォート ( " ) とバックスラッシュ ( \ ) 以外である。また 以下のエスケープシーケンスをサポートする。 表記 意味 ¥" 二重引用符 (quotation mark) ¥¥ バックスラッシュ (reverse solidus) ¥/ スラッシュ (solidus) ¥b 後退 (バックスペース) (backspace) ¥f 改ページ (formfeed) ¥n 改行 (newline) ¥r 復帰 (carriage return) ¥t タブ (horizontal tab) ¥uXXXX 4 桁の 16 進数で表記された Unicode 文字 (4 hexadecimal digits) なおサーバから JSON で出力する場合には、バックスラッシュ自体がエスケープ文字とみな されてしまうため、「¥¥n」のようにバックスラッシュをエスケープする必要がある。 オブジェクト (object) オブジェクトは、基本的にオブジェクトリテラルの形式で記述する。しかしそれとは異なり、 プロパティ名は文字列としてダブルクォート ( " ) で囲む必要がある。 ※最後の要素の後にカンマ (,) を付けてはいけない。 配列 (array) 配列は配列リテラルの形式で記述します。 ※最後の要素の後にカンマ (,) を付けてはいけない。 論理値 (true、false) 「true」「false」と記述する。 null 「null」と記述する。 JSON 文字列と JavaScript オブジェクトの相互変換 JSON オブジェクトがサポートされるならば、そのメソッドにより JSON 文字列と JavaScript オブジェクトを簡単に変換できる。それがサポートされるかどうかは、簡単には Window オ ブジェクトに JSON プロパティが存在するかどうかで判別できる。 if( window.JSON ) { // JSON がサポートされる } JSON の parse と stringify メソッドの使い方 JSON.parse JSON.parse()メソッドは JSON 文字列を解析して JavaScript のオブジェクトに変換する。 JSON.parse(text [, reviver]) 引数 text JSON として解析する文字列。 reviver(任意) もし関数である場合、解析により作り出された元の値を、オブジェクトを返す前に変換する 方法を指示する。 戻り値 text として与えられた JSON に相当する Object を返す。 基本的な変換は次の通り。 JSON.parse('{}'); // {} -> [object Object] JSON.parse('{"bar": 1234, "foo": undefined}'); // {bar: 1234} -> [object Object] JSON.parse('"foo"'); // "foo" -> [object String] JSON.parse('true'); // true -> [object Boolean] JSON.parse('[1, 5, false]'); // [1, 5, false] -> [object Array] JSON.parse()に渡す JSON 文字列は JSON 構文に準拠する必要があるため、次のようなパタ ーンはエラーが発生する。 1 ・文字列がダブルクオーテーションで括られていない。 2 ・真偽値(true / false)や null が大文字。 3 ・オブジェクトのキーが文字列でない。 JSON.parse("hoge"); // 文 字 列 が ダ ブ ル ク ォ ー テ ー シ ョ ン で 括 ら れ て い な い 。 JSON.parse("'hoge'"); // 文字列がシングルクォーテーションで括られている。 JSON.parse('Null'); // 先 頭 が 大 文 字 な の で 文 字 列 と し て 認 識 さ れ て エ ラ ー に な る 。 JSON.parse('True'); // 先頭が大文字なので文字列として認識されてエラーになる。 JSON.parse('"true"'); // エラーにはならないが String 型に変換される。 JSON.parse('{1234: true}'); // キーが文字列じゃない(ダブルクォーテーションで括られて いない) reviver 引数の使用 もし reviver が指定されている場合、解析によって計算された値は、オブジェクトを返す前に 変換される。正確に言えば、計算された値とそのすべてのプロパティ(最もネストされたプ ロパティから始まり、元の値へと進む)はそれぞれ reviver を通して変換される。reviver は処 理されるプロパティを含むオブジェクトが this として、また文字列のプロパティ名とプロパ ティの値を引数として呼び出される。もし reviver 関数が undefined を返したり、何の値も返 さなかったり(例えば実行が関数の終わりで【訳注: return 文によってではなくて】終了した 場合)した場合、そのプロパティはオブジェクトから削除される。そうでなければそのプロ パティはその戻り値として再定義される。 もし reviver が一部の値だけを変換して他を変換しないのであれば、必ずすべての変換され ない値をそのまま返すようにする。そうしなければ、それらの値は結果のオブジェクトから 削除される。 JSON.parse('{"p": 5}', function(k, v) { if (typeof v === 'number') { return v * 2; // 数字については v * 2 を返す } return v; // 他のすべてはそのまま返す }); // { p: 10 } JSON.parse('{"1": 1, "2": 2, "3": {"4": 4, "5": {"6": 6}}}', function(k, v) { console.log(k); // 現在のプロパティ名を出力する。最後は ""。 return v; // 変更されていないプロパティの値を返す。 }); // 1 // 2 // 4 // 6 // 5 // 3 // "" JSON.stringify JSON.stringify()メソッドは JavaScript の値を JSON 文字列に変換する。 JSON.stringify(value[, replacer[, space]]) 引数 value JSON 文字列に変換する値。 replacer(任意) 文字列化の手順の挙動を置き換える関数、または String と Number オブジェクトの配列 であって、値のオブジェクトを JSON 文字列に含めるプロパティを選択するホワイトリ ストとして機能するもの。もしこの値が null であるか提供されない場合は、オブジェク トのすべてのプロパティが結果の文字列に含まれる。 space(任意) 出力する JSON 文字列に可読性を目的に空白を挿入するために使う String または Number オブジェクト。これが Number のときは空白として使う空白文字の数を示す。こ の数字は上限が 10 に設定されていて 10 より大きい場合 10 となる。1 より小さい値は空 白を使わないことを示す。これが String のときはその文字列(10 文字より長い場合はそ の最初の 10 文字)が空白として使われる。もしこの引数が提供されない(または null で ある)場合は、空白は使用されない。 説明 配列でないオブジェクトのプロパティは、特定の順序で文字列化されることを保証 されてはいません。文字列化において同じオブジェクトのプロパティの順序付けを信用 しないようにする。 Boolean、Number と String オブジェクトは文字列化の際に対応するプリミティブ (ある大きな構造を表現するのに使われる、もっとも基本的な構成要素 )な値に変換 される。 もし変換の際に undefined、関数、またはシンボルに出会った場合、それは省略さ れる(オブジェクトで見つかった時)か null に変更される(配列で見つかった時)こ と に な る 。 ま た JSON.stringify は JSON.stringify(function(){}) や JSON.stringify(undefined) のように「純粋」な値を渡した場合に undefined を返すこ とがある。 プロパティのキーがシンボルであるプロパティはすべて、replacer 関数を使用する 場合でも完全に無視される。 enumerable でないプロパティは無視される。 基本的な変換は次の通り。undefined や関数、Symbol が存在した場合、オブジェクトの場合は 削除され、配列の場合は null に置き換えられる。 JSON.stringify({}); // '{}' JSON.stringify({ x: 10, y: undefined, z: 20 }); // '{"x":10,"z":20}' JSON.stringify("foo"); // '"foo"' JSON.stringify(true); // 'true' JSON.stringify([1, "false", false, undefined]); // '[1,"false",false,null]' JSON.stringify(null); // 'null' replacer は省略可能である。関数を指定した場合は文字列を返す前にプロパティ値を変換す る。 replacer の関数はオブジェクトの場合プロパティ名とプロパティの値を引数として呼びださ れる。関数が undefined を返した場合、そのプロパティは結果のオブジェクトから削除され、 有効な値を返した場合はその戻り値としてプロパティが再定義される。JSON.parse()と同じ ようにルートオブジェクトのプロパティ名が空で呼ばれるので値をそのまま返さないとい けない。 JSON.stringify({"one": 1, "two": 2, "three": true}, function(key, value) { if (key === '') return value; if (Number.isFinite(value)) { return String(value * 2); // 数字の場合は 2 を掛けて文字列として出力 } else { return undefined; // 数字のみを返したい } }); replacer に配列を指定した場合は配列にあるプロパティだけが保持される。 space は省略可能である。指定した数値や文字列で結果を整形して出力する。 JSON.stringify({one: 1, two: 2}, null, 2); //"{ // "one": 1, // "two": 2 //}" JSON.stringify({one: 1, two: 2}, null, '\t'); //"{ // "one": 1, // "two": 2 //}" http://www.task-notes.com/entry/20160719/1468858991 JSON の parse と stringify メソッドの使 い方 eval()関数による変換 JSON 形式の文字列データは、eval()関数で評価することでも JavaScript のオブジェクトに変 換できる。このとき eval()に渡す文字列はかっこで囲む必要がある。さもなくば「SyntaxError: invalid label」として例外が発生する。 var data = '{ "property1":"text", "property2":10 }'; var obj = eval( '(' + data + ')' ); このコードを実行すると obj は、 のようになる。 ※eval()の使用には危険が伴うため、信頼できるデータ以外には使用しては いけないらし い。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/ev al eval()について JSON ファイルを読み込む getJSON() ファイル形式 エンコーディング UTF-8 .json 拡張子 MIME タイプ application/json getJSON( url [, data] [, callback] ) 外部 json ファイルを読み込むには、「$.getJSON」メソッドを使用する。 引数 型 説明 url String リクエストの送信先 URL data(オプション) Map リクエスト先に送信する値 callback(オプション) Function リクエスト成功時のコールバ ック関数 getJSON()をつかったサンプル getJSON()を使って、sample.json を読み込みアラート表示する簡単なサンプル。 sample.json {"first_name":"一郎","last_name":"鈴木"} jQuery $.getJSON("sample.json", function(json){ alert(data.last_name + data.first_name);// 鈴木一郎とアラート表示 }) json は{名前:値}のセットで記述されている。 受け取った json ファイルは、サンプルでは「json」という変数に格納され、 「json.名前」で値を 取り出すことができる。 参考文献 http://www.json.org/json-ja.html 「JSON の紹介」 http://www.gixo.jp/blog/4288 「CSV、XML、JSON…データフォーマットの変遷について考え る」 http://uxmilk.jp/8813 「jQuery で json ファイルを読み込む方法:getJSON()」