JSONの書き方について考えてみた・2
昨日の続き。
はてブの注目のエントリーに入ったのを見て、『考えてみた』ではなく『考察』と、かっこいいタイトルにしておけばよかったと思いつつも、このままでいきます。
冒頭部での読み込み完了コールバックの仕込み
追加対応型だと、最後に読み込み完了のコールバックを書くことができません。
「最後にコールバックをかけないのなら、冒頭部にコールバックを書けばいいのに。」とどこかの王妃が言ったかどうかは知りませんが、
if (typeof(Hoge) == 'undefined') Hoge = {}; Hoge.data = []; if (typeof(Hoge.onload) == 'function') { Hoge.onload(Hoge.data); } Hoge.data.push('text');
このように書いても駄目なのは明らかです。空の配列が渡されます。
次のように書くとうまくいきます。
/* 略 */ if (typeof(Hoge.onload) == 'function') { setTimeout(function(){Hoge.onload(Hoge.data);}, 0); } /* 略 */
0ミリ秒後に実行ということで、先ほどのと変わらないようにも思えますが、setTimeoutのカウントが一連の処理が終わってから始まるようで、うまいことに読み込みが完了してから呼び出されます。(windows版IE、Firefoxで確認)
先頭評価値の指定
JSONのデータをオブジェクトに格納する書き方をした場合、最初にそのオブジェクトを用意する必要があります。
if (typeof(Hoge) == 'undefined') Hoge = {};
このため、次のやり方で取得しようとするとエラーになります。
eval('var data = ' + jsonText);
そこで、無理やり解決してみます。
(function() { if (typeof(Hoge) == 'undefined') Hoge = {}; Hoge.data = []; return Hoge.data; })(); Hoge.data.push('text');
冒頭の処理を無名関数にすることで、最初の評価値を任意の値に変えてしまいます。
追加対応型をeval戻り値での取得に対応させる
追加対応型を利用すると、最後の評価値は最後に追加したデータになります。
if (typeof(Hoge) == 'undefined') Hoge = {}; Hoge.data = []; Hoge.data.push('text'); Hoge.data.push('hoge'); Hoge.data.push('fuga');
これだと、
var data = eval(jsonText);
とするとdataは'fuga'になります。
どうしてもevalの引数で取得したいという場合は、こうすると何とかなります。
if (typeof(Hoge) == 'undefined') Hoge = {}; Hoge.data = []; Hoge.data.push('text'); Hoge.data.push('hoge'); Hoge.data.push('fuga'); Hoge.data
見てわかるように、最後にHoge.dataを追加しただけです。
ここにデータを追加する場合は、
.push('foo'); Hoge.data
を追加しましょう。
まとめ
ひとつにまとめてみた。
(function() { if (typeof(Hoge) == 'undefined') Hoge = {}; Hoge.data = []; return Hoge.data; })(); if (typeof(Hoge.onload) == 'function') { setTimeout(function(){ Hoge.onload(Hoge.data); }, 0); } Hoge.data.push('text'); Hoge.data.push('hoge'); Hoge.data.push('fuga'); Hoge.data
これで、XMLHTTPRequest+evalでの2通りの取得可能、script要素を使った別ドメインからの利用も読み込み完了コールバックつきで可能、データの追加は追加書き込みで可能という豪華なJSONができました。
正直なところ、先頭評価値の指定はなくていい気もしますが。
あとがき
これまでJSONといい続けたのですが
どう見てもJavaScriptコードです。
本当にありがとうございました
JSONの仕様から逸脱したかたちになりましたが、JavaScriptでの利用と割り切ればこういった形もアリではないでしょうか。