JavaScript プログラミング講座

 

JSON とは?

 


■JSON とは?


JSON は、「JavaScript Object Notation」の略で「ジェイソン」といいます。
 
テキストフォーマットの一種です。シンプルで軽量です。
 
JSON は、null、真偽値、数値、文字列、配列、オブジェクト(連想配列)のデータを、文字列で表現できます。
 
配列とオブジェクト(連想配列)は、ネスト(入れ子)構造で表現する事ができます。
 
ECMAScript 系の言語であれば、「オブジェクト(ECMAScript)」と「JSON 文字列」の相互変換を、簡単に行うことができます。
 
他言語で扱う場合でも、XML と比べて比較的仕様が簡単なので、導入が容易でしょう。
 

■ブラウザが JSON パース機能をサポートしているか調べる

 
ブラウザが、JSON パース機能をサポートしているか調べるには、window.JSON が真であるか比較します。
 
 


 

JSON のフォーマットについて

 


■JSON のフォーマットについて

 
JavaScript にて、配列とオブジェクトを作成したい場合、以下の様なリテラル表記を使用することができます。
 
■JavaScript で配列を作成する場合
 
初期データを格納しつつ、配列を作成するには、配列リテラルを使用します。
 
初期データを格納して配列を作成

var ary = [true , false , 0 , 1 , 2 , 0.345 , "あ" , "い"];
 
■JavaScript でオブジェクトを作成する場合
 
初期データを格納しつつ、オブジェクトを作成するには、オブジェクトリテラルを使用します。
 
初期データを格納してオブジェクトを作成

var obj = {
	a : true,
	b : false,
	c : 0,
	d : 1,
	e : 2,
	f : 0.345,
	g : "あ",
	h : "い"
};
 
■JSON 形式について
 
JavaScript のリテラル表記に近い形で、文字列として表現したものが、JSON 形式です。
 
空白、タブ、改行などの整形用の文字は、自由に挿入する事ができます。
 

■JSON 形式で null 値を表現する

 
JSON では、null と記述すると、null 値を表現できます。
 
undefined 値を表現する事はできません。
 
null 値を JSON で表現する

null
 

■JSON 形式で数値を表現する

 
整数、小数、指数を表現できます。
 
「16 進数」や 「8 進数」の表記を使用する事はできません。
 
NaN 値や、Infinity 値を表現する事はできません。
 
整数値を JSON で表現する

123
 
小数値を JSON で表現する

-123.456
 
指数を JSON で表現する

1.2345e+4
 

■JSON 形式で文字列を表現する

 
文字列は、ダブルクォーテーション『" "』 でくくります。
 
シングルクォーテーション『' '』でくくる事はできません。
 
文字列を JSON で表現する

"あいうえお"
 
■エスケープ文字について
 
エスケープで表現できる文字は、以下の通りです。
 
表記Unicode説明
\bU+0008バックスペース
\fU+000Cフォームフィード
\nU+000Aラインフィード(改行コード)
\rU+000Dキャリッジ・リターン(改行コード)
\tU+0009タブ
\"U+0022ダブルクォーテーション
\/U+002Fスラッシュ
\\U+005Cバックスラッシュ(円記号)
 
エスケープを含めた文字列を JSON で表現する

"\tあいうえお\n\tかきくけこ"
 
■Unicodeスカラ値について
 
\uFFFF と記述すると、Unicode 1文字分を表現できます。
 
FFFF の部分には、ユニコードを 16 進数で表記します。
 
サロゲートペアとなるコードは、2つに分けて表記します。
 
例えば、U+10FFFF 文字は、\uD83F\uDFFF と表記します。
 
Unicodeスカラ値を含めた文字列を JSON で表現する

"\u3042 \u3044 \u3046 \u3048 \u304a"
 

■JSON 形式で配列を表現する

 
配列リテラルの書式を、そのまま利用できます。
 
配列を JSON で表現する

[ true , false , 0 , 1 , 2 , 0.345 , "あ" , "い" ]
 
多次元配列を JSON で表現する

[
	[
		["A","B","C"],
		["D","E","F"],
		["G","H","I"]
	],[
		["J","K","L","M"],
		["N","O","P","Q","R"]
	],[
		[
			["S","T","U"],
			["V","W"]
		],[
			["X"],
			["Y"],
			["Z"]
		]
	]
]
 

■JSON 形式でオブジェクトを表現する

 
オブジェクトのキーの部分は、文字列の表現と同じです。
 
必ずダブルクォーテーション『" "』 でくくる必要があります。
 
シングルクォーテーション『' '』でくくる事はできません。
 
また、クォーテーション表記を省略することもできません。
 
オブジェクトを JSON で表現

{ "a":true , "b":false , "c":0 , "d":1 , "e":2 , "f":0.345 , "g":"あ" , "h":"い" }
 
配列とオブジェクトの組み合わせを JSON で表現

{
	"aaa":{
		"count":123,
		"name":"テスト1",
		"result":false
	},
	"bbb":{
		"count":456,
		"name":"テスト2",
		"result":true
	},
	"ccc":{
		"count":789,
		"name":"テスト3",
		"param":{
			"ary":["a","b","c"],
			"name":"テスト4"
		},
		"result":true
	}
}
 


 

オブジェクトから JSON 文字列に変換する

 
 
 


■JSON.stringify() メソッドを使用する


「JavaScript のオブジェクト」から、「JSON 文字列」に変換するには、JSON.stringify() メソッドを使用します。
 
Internet Explorer 8 以降で利用可能です。
 
JSON.stringify( オブジェクト , データ変換 , 整形 ) :String
第01引数 *オブジェクトや配列を指定。文字列、数値、真偽値、null でも可能。
第02引数(略可)*データ変換用コールバック関数を指定。もしくは、出力したいプロパティ名が格納された配列を指定。
第03引数(略可)*整形用文字列(空白、タブ、改行)を指定。もしくは、空白の個数を数値で指定。
戻り値 StringJSON 文字列が得られる。
 
「JavaScript のオブジェクト」から「JSON 文字列」に変換する

// JSON をサポートしている
if(window.JSON){

	// ------------------------------------------------------------
	// JavaScript のオブジェクトを用意する
	// ------------------------------------------------------------
	var obj = {
		aaa:{
			count :123,
			name  :"テスト1",
			result:false
		},
		bbb:{
			count :456,
			name  :"テスト2",
			result:true
		},
		ccc:{
			count :789,
			name  :"テスト3",
			param :{
				ary :["a","b","c"],
				name:"テスト4"
			},
			result:true
		}
	};

	// ------------------------------------------------------------
	// 「JavaScript のオブジェクト」から「JSON 文字列」に変換する
	// ------------------------------------------------------------
	var json_text = JSON.stringify(obj);

	// テスト出力
	console.log(json_text);

}
 
■第02引数(コールバック関数を指定した場合)
 
データを変換するための、コールバック関数を指定する事ができます。
 
第01引数から、キー情報が得られます。(文字列型)
 
配列なら番地、オブジェクトならプロパティ名です。それ以外なら、空文字 "" が得られます。
 
第02引数から、本来の値情報が得られます。
 
戻り値から、新しい値情報を指定します。
 
undefined を返すと、プロパティを結果から除外する事ができます
 
入力データが、ネスト(入れ子)構造である場合、始祖から子孫へと順番に実行されます。
 
JSON.stringify() メソッドの第02引数に、変換用コールバック関数を指定する。

// JSON をサポートしている
if(window.JSON){

	// ------------------------------------------------------------
	// JavaScript のオブジェクトを用意する
	// ------------------------------------------------------------
	var obj = {
		aaa:["A0","A1","A2"],
		bbb:{
			ccc:"C",
			ddd:"D",
			eee:{
				fff:"F",
				ggg:"G"
			}
		}
	};


	// ------------------------------------------------------------
	// データ変換用コールバック関数
	// ------------------------------------------------------------
	function JsonStringifyReplacer(key,value){

		// 出力テスト
		console.log("key:" + key + " value:" + value);

		// 変換したい値を返す(ここでは本来の値をそのまま返している)
		return value;
	}

	// ------------------------------------------------------------
	// 「JavaScript のオブジェクト」から「JSON 文字列」に変換する
	// ------------------------------------------------------------
	var json_text = JSON.stringify(obj,JsonStringifyReplacer);

	// テスト出力
	console.log(json_text);

}
 
■第02引数(配列を指定した場合)
 
任意のオブジェクトのプロパティを、結果に含めるかどうかを、配列形式で指定する事ができます。
 
オブジェクト型にのみ作用します。それ以外の型はすべて出力されます。
 
出力を許可したい場合、配列にプロパティ名を登録します。
 
JSON.stringify() メソッドの第02引数に、出力したいオブジェクトのプロパティ名を、配列形式で指定する。

// JSON をサポートしている
if(window.JSON){

	// ------------------------------------------------------------
	// JavaScript のオブジェクトを用意する
	// ------------------------------------------------------------
	var obj = {
		aaa:["A0","A1","A2"],
		bbb:{
			ccc:"C",
			ddd:"D",
			eee:{
				fff:"F",
				ggg:"G"
			}
		}
	};


	// ------------------------------------------------------------
	// 出力を許可したいプロパティを、配列に格納する
	// ------------------------------------------------------------
	var json_stringify_allow = [
		"aaa",
		"bbb",
		"ddd"
	];

	// ------------------------------------------------------------
	// 「JavaScript のオブジェクト」から「JSON 文字列」に変換する
	// ------------------------------------------------------------
	var json_text = JSON.stringify(obj,json_stringify_allow);

	// テスト出力
	console.log(json_text);

}
 

■代替関数を使用する

 
「JavaScript のオブジェクト」から「JSON 文字列」に変換する関数です。
 
Internet Explorer 6 以降や、ActionScript1.0 (Flash 6 以降) でも動作します。
 
「JavaScript のオブジェクト」から「JSON 文字列」に変換する関数

// ------------------------------------------------------------
// 「JavaScript のオブジェクト」から「JSON 文字列」に変換する関数
// ------------------------------------------------------------
function JsonStringify(obj){
	var dic_e = new Object();
	dic_e['\b'] = '\\b';
	dic_e['\f'] = '\\f';
	dic_e['\n'] = '\\n';
	dic_e['\r'] = '\\r';
	dic_e['\t'] = '\\t';
	dic_e['\"'] = '\\"';
	dic_e['\\'] = '\\\\';

	function stringify(obj){
		var i;
		var k;
		var s;
		var r;
		var num;
		var type = typeof(obj);
		if(type == "object"){
			if(!obj){
				return "null";

			// 配列
			}else if(obj.constructor == Array){
				s = "[";
				num = obj.length;
				for(i=0;i < num;i++){
					if(i)	s += ",";
					s += stringify(obj[i]);
				}
				return s + "]";

			// オブジェクト
			}else{
				r = false;
				s = "{";
				for(k in obj){
					if(r)	s += ",";
					else	r = true;
					s += stringify(k) + ":" + stringify(obj[k]);
				}
				return s + "}";
			}

		// 文字列
		}else if(type == "string"){
			s = '"';
			num = obj.length;
			for(i=0;i < num;i++){
				if(dic_e[obj.charAt(i)] != undefined){
					s += dic_e[obj.charAt(i)];
				}else{
					s += obj.charAt(i);
				}
			}

			return s + '"';

		// 数値
		}else if(type == "number"){
			if(isNaN(obj)) return "null";
			if(obj == Number.POSITIVE_INFINITY) return "null";
			if(obj == Number.NEGATIVE_INFINITY) return "null";
			return obj.toString();

		}else if(type == "boolean"){
			return obj.toString();
		}else if(type == "null" || type == "undefined"){
			return "null";
		}
		return null;
	}

	return stringify(obj);
}
 
■使用例
 
「JavaScript のオブジェクト」から「JSON 文字列」に変換する

// ------------------------------------------------------------
// JavaScript のオブジェクトを用意する
// ------------------------------------------------------------
var obj = {
	key_null  :[ null , undefined ],
	key_bool  :[ false , true ],
	key_number:[ 0 , -123 , 987.654 , Number.MIN_VALUE , Number.MAX_VALUE , Number.NaN , Number.POSITIVE_INFINITY , Number.NEGATIVE_INFINITY ],
	key_string:[ "あいうえお" , "/ \b \f \n \r \t \" \\" ],
	key_array :[ "a" , "b" , "c" ],
	key_object:{
		aaa:0,
		bbb:1,
		ccc:2
	}
};

// ------------------------------------------------------------
// 「JavaScript のオブジェクト」から「JSON 文字列」に変換する
// ------------------------------------------------------------
var json_text = JsonStringify(obj);

// 出力テスト
console.log(json_text);
 


 

JSON 文字列からオブジェクトに変換する

 
 
 


■JSON.parse() メソッドを使用する

 
「JSON 文字列」から「JavaScript のオブジェクト」に変換するには、JSON.parse() メソッドを使用します。
 
Internet Explorer 8 以降で利用可能です。
 
JSON.parse( "JSON 文字列" , コールバック関数 ) :*
第01引数 StringJSON 文字列を指定。
第02引数(略可)Functionデータ変換用コールバック関数を指定。
戻り値 *オブジェクトや配列が得られる。もしくは、文字列、数値、真偽値、null が得られる。
 
「JSON 文字列」から「JavaScript のオブジェクト」に変換する

// JSON をサポートしている
if(window.JSON){

	// ------------------------------------------------------------
	// JSON 文字列を用意する
	// ------------------------------------------------------------
	var json_text = '{"ary":[0,1,2],"obj":{"a":0,"b":1,"c":2}}';


	// ------------------------------------------------------------
	// 「JSON 文字列」から「JavaScript のオブジェクト」に変換する
	// ------------------------------------------------------------
	var obj = JSON.parse(json_text);

	// テスト出力
	console.log(obj);

}
 
■第02引数(コールバック関数)
 
データを変換するための、コールバック関数を指定する事ができます。
 
第01引数から、キー情報が得られます。(文字列型)
 
配列なら番地、オブジェクトならプロパティ名です。それ以外なら、空文字 "" が得られます。
 
第02引数から、本来の値情報が得られます。
 
戻り値から、新しい値情報を指定します。
 
undefined を返すと、プロパティを結果から除外する事ができます
 
入力データが、ネスト(入れ子)構造である場合、子孫から始祖へと順番に実行されます。
 
JSON.parse() メソッドの第02引数に、変換用コールバック関数を指定する。

// JSON をサポートしている
if(window.JSON){

	// ------------------------------------------------------------
	// JSON 文字列を用意する
	// ------------------------------------------------------------
	var json_text = '{"aaa":["A0","A1","A2"],"bbb":{"ddd":"D","eee":{"ggg":"G","fff":"F"},"ccc":"C"}}';


	// ------------------------------------------------------------
	// データ変換用コールバック関数
	// ------------------------------------------------------------
	function JsonParseReviver(key,value){

		// 出力テスト
		console.log("key:" + key + " value:" + value);

		// 変換したい値を返す(ここでは本来の値をそのまま返している)
		return value;
	}

	// ------------------------------------------------------------
	// 「JSON 文字列」から「JavaScript のオブジェクト」に変換する
	// ------------------------------------------------------------
	var obj = JSON.parse(json_text,JsonParseReviver);

	// テスト出力
	console.log(obj);

}
 

■eval() 関数を使用する(非推奨)

 
eval 関数を使用すると、「JSON 文字列」から「JavaScript のオブジェクト」に変換する事ができます。
 
ただし、セキュリティリスクがあるため、通常は JSON.parse() メソッドを使用します。
 
■セキュリティリスクについて
 
外部から得られる不定の文字列を、eval() 関数に渡してはいけません。
 
eval() 関数を使用すると、文字列から JavaScript を実行する事ができます。
 
外部から、悪意ある JavaScript コードが実行できるようになり、非常に危険です。
 
■使用例
 
eval 関数を使って、JSON 文字列をオブジェクトに変換(注.セキュリティリスクあり)

// ------------------------------------------------------------
// 「JSON 文字列」から「JavaScript のオブジェクト」に変換する関数
// ------------------------------------------------------------
function JsonParse(text){
	return eval("(" + text + ")");
}

// ------------------------------------------------------------
// JSON 文字列を用意する
// ------------------------------------------------------------
var json_text = '{"ary":[0,1,2],"obj":{"a":0,"b":1,"c":2}}';

// ------------------------------------------------------------
// 「JSON 文字列」から「JavaScript のオブジェクト」に変換する
// ------------------------------------------------------------
var obj = JsonParse(json_text);

// テスト出力
console.log(obj);
 

■代替関数を使用する

 
「JSON 文字列」を解析して「JavaScript のオブジェクト」に変換する関数です。
 
Internet Explorer 6 以降や、ActionScript1.0 (Flash 7 以降) でも動作します。
 
「JSON 文字列」から「JavaScript のオブジェクト」に変換する関数

// ------------------------------------------------------------
// 「JSON 文字列」から「JavaScript のオブジェクト」に変換する関数
// ------------------------------------------------------------
function JsonParse(text){
	var pre_w = new Object();
	var pre_u = new Object();
	var pre_b = new Object();
	var pre_n = new Object();
	var pre_s = new Object();
	var pre_a = new Object();
	var pre_o = new Object();
	var dic_d = new Object();
	var dic_e = new Object();
	pre_u['n'] = pre_b['t'] = pre_b['f'] = pre_s['"'] = pre_a['['] = pre_o['{'] = pre_w[' '] = pre_w['\t'] = pre_w['\r'] = pre_w['\n'] = true;
	pre_n['0'] = pre_n['1'] = pre_n['2'] = pre_n['3'] = pre_n['4'] = pre_n['5'] = pre_n['6'] = pre_n['7'] = pre_n['8'] = pre_n['9'] = pre_n['-'] = true;
	dic_d['0'] = dic_d['1'] = dic_d['2'] = dic_d['3'] = dic_d['4'] = dic_d['5'] = dic_d['6'] = dic_d['7'] = dic_d['8'] = dic_d['9'] = true;
	dic_e['/'] = '/'; dic_e['b'] = '\b'; dic_e['f'] = '\f'; dic_e['n'] = '\n'; dic_e['r'] = '\r'; dic_e['t'] = '\t'; dic_e['\"'] = '\"'; dic_e['\\'] = '\\';

	var p = 0;
	var num = text.length;

	function skip(){
		while(pre_w[text.charAt(p)]){
			p++;
			if(p >= num){
				return;
			}
		}
	}

	function parse(){
		var r;
		var c;
		var w;
		var s;
		var e;

		skip();
		c = text.charAt(p);

		// オブジェクト
		if(pre_o[c]){
			var obj = new Object();

			p++;
			skip();
			r = true;
			while(true){
				c = text.charAt(p);
				if(c == '}'){
					if(!r) throw("JsonParse: Missing comma(,) position:" + p);
					p++;
					break;
				}
				if(c != '"') throw("JsonParse: Missing double quote(\") position:" + p);

				w = parse();

				skip();
				if(text.charAt(p) != ':') throw("JsonParse: Missing semicolon(:) position:" + p);
				p++;
				skip();

				obj[w] = parse();

				skip();
				if(p >= num){ throw("JsonParse: Missing curly bracket(}) position:" + p); }

				r = (text.charAt(p) != ',');
				if(!r){
					p++;
					skip();
				}
			}

			return obj;

		// 配列
		}else if(pre_a[c]){
			var ary = new Array();

			p++;
			skip();
			r = true;
			while(true){
				if(text.charAt(p) == ']'){
					if(!r) throw("JsonParse: Missing comma(,) position:" + p);
					p++;
					break;
				}

				ary.push(parse());

				skip();
				if(p >= num){ throw("JsonParse: Missing square bracket(]) position:" + p); }

				r = (text.charAt(p) != ',');
				if(!r){
					p++;
					skip();
				}
			}

			return ary;

		// 文字列
		}else if(pre_s[c]){
			p++;

			var str = "";
			while(true){
				if(p >= num)  throw("JsonParse: Missing double quote(\") position:" + p);
				c = text.charAt(p);
				p++;
				if(c == '"'){
					break;
				}else if(c == "\\"){
					c = text.charAt(p);
					p++;
					if(c == 'u'){
						e = 0;
						r = ((num - p) > 4);
						if(r){
							s = text.charCodeAt(p);
							if(!s)			s = 0;
							if(s >= 97)		s -= 87;
							else if(s >= 65)	s -= 55;
							else			s -= 48;
							if(0 <= s && s < 16){
								e += s * 0x1000;
								p++;
							}else{
								r = false;
							}
						}
						if(r){
							s = text.charCodeAt(p);
							if(!s)			s = 0;
							if(s >= 97)		s -= 87;
							else if(s >= 65)	s -= 55;
							else			s -= 48;
							if(0 <= s && s < 16){
								e += s * 0x0100;
								p++;
							}else{
								r = false;
							}
						}
						if(r){
							s = text.charCodeAt(p);
							if(!s)			s = 0;
							if(s >= 97)		s -= 87;
							else if(s >= 65)	s -= 55;
							else			s -= 48;
							if(0 <= s && s < 16){
								e += s * 0x0010;
								p++;
							}else{
								r = false;
							}
						}
						if(r){
							s = text.charCodeAt(p);
							if(!s)			s = 0;
							if(s >= 97)		s -= 87;
							else if(s >= 65)	s -= 55;
							else			s -= 48;
							if(0 <= s && s < 16){
								e += s * 0x0001;
								p++;
							}else{
								r = false;
							}
						}
						if(r){
							str += String.fromCharCode(e);
						}else{
							throw("JsonParse: Invalid codepoint. position:" + p);
						}
					}else if(dic_e[c] != undefined){
						str += dic_e[c];
					}else{
						throw("JsonParse: Invalid escape. position:" + (p-1));
					}
				}else{
					str += c;
				}
			}
			return str;

		// 数値
		}else if(pre_n[c]){
			s = p;
			p ++;

			while(dic_d[text.charAt(p)]){
				p++;
			}

			r = false;
			if(text.charAt(p) == '.'){
				p++;
				r = true;

				if(!dic_d[text.charAt(p)]){
					throw("JsonParse: Missing digits after decimal. position:" + p);
				}
				p++;

				while(dic_d[text.charAt(p)]){
					p++;
				}
			}
			if(text.charAt(p) == 'e'){
				p++;
				r = true;

				c = text.charAt(p);
				if(c == '+' || c == '-'){
					p++;
				}

				if(!dic_d[text.charAt(p)]){
					throw("JsonParse: Missing digits after exponent. position:" + p);
				}
				p++;

				while(dic_d[text.charAt(p)]){
					p++;
				}
			}

			if(r)	return parseFloat(text.substring(s,p));
			else	return parseInt(text.substring(s,p));

		// 真偽値
		}else if(pre_b[c]){
			w = text.substr(p, 5);
			if(w == "false"){
				p += 5;
				return false;
			}
			if(w.indexOf("true") == 0){
				p += 4;
				return true;
			}

		// null 値
		}else if(pre_u[c]){
			if(text.substr(p, 4) == "null"){
				p += 4;
				return null;
			}
		}

		throw("JsonParse: Unable to parse value. position:" + p);
	}

	var data = parse();
	skip();
	if(p < num) throw("JsonParse: Unexpected character after JSON. position:" + p);
	return data;
}
 
■使用例
 
「JSON 文字列」から「JavaScript のオブジェクト」に変換する

// ------------------------------------------------------------
// JSON 文字列を用意する
// ------------------------------------------------------------
var json_text = '{"key_null":null,"key_bool":[false,true],"key_number":[0,-123,987.654,5e-324,1.7976931348623157e+308],"key_string":["あいうえお","\\/ \\b \\f \\n \\r \\t \\" \\\\"],"key_array":["a","b","c"],"key_object":{"aaa":0,"bbb":1,"ccc":2}}';

// ------------------------------------------------------------
// 「JSON 文字列」から「JavaScript のオブジェクト」に変換する
// ------------------------------------------------------------
var obj = JsonParse(json_text);

// 出力テスト
console.log(obj);