JSON
 
HOME
LAJAXS
JSON
カレンダーコントロール
Homepage
Blog
 

Last Update: 2005/12/03
新規作成。

About JSON

 JavaScript の仕様に基づく軽量なデータ交換形式で、詳しくは「Introducing JSON」(日本語訳)を参照してください。。

{
 property_1:1, ←数値
 property_2:"文字列" ←文字列
 property_3:[1,2,3], ←配列
 method_1:function() { ←関数
  alert("<日本語>");
 }
}

こんな形式のデータで、JavaScript のオブジェクトを交換できます。xml と同等以上のデータを交換でき、かつ軽量(データサイズやエンコード、デコード処理)である事が利点です。AJAX でこれを利用する場合、主にサーバーから受け取ったデータをテキスト形式で取り出し、

var obj = eval('(' + XmlHTTPRequest.responseText +')');
obj.function();
alert(obj.property_2);

こんな風にエンコードして利用します。

JSON in XML

 上記で利用方法を簡単に紹介しましたが、日本語を扱う場合に少し注意が必要になります。
 昨今のデータ交換形式には UTF-8が多く用いられる様になりました。日本語を扱う場合も UTF-8のテキストをサーバーから送れば万事OK...だと良かったのですが、ブラウザによっては UTF-8 でデータを送っても正しく日本語にエンコードできない問題が発生します。これを解決する方法として、テキストデータをURIエンコードしてから送出すると言うアプローチが紹介されています。しかし、JSONを使用する主な理由はそれが軽量だからです。残念ながらこの方法ではそれがスポイルされてしまうのでは?と思います。

 一方で、responseXML による xml 形式での受信の場合は、この様な問題は殆ど発生しない*1様です。そこで、JSON も xml もデータコンテナであると言う特徴を利用させて貰う事にしましょう。つまり、xml 形式で JSON データを運べば問題は解決します。

<?xml version="1.0" encoding="utf-8" ?>
<j>{
 property_1:1,
 property_2:"日本語を含む utf-8 のデータ",
 property_3:[1,2,3],
 method_1:function() {
  alert("&lt;タグはエスケープすれば良し&gt;");
 }
}</j>
 

こんな風な形式でデータを送れば、文字化けせずに軽量なデータのやり取りが出来る様になります。
クライアント側では、

var obj = eval('(' + XmlHTTPRequest.responseXML.documentElement.text +')');

で利用できます。

*1これに問題があるのはやはりバグと呼んで良いでしょう。ここではブラウザ(Konqueror)が対応するのを待つ事にします。

JSON in HTML

 非同期では無いので AJAX ではありませんが、サーバーから貰ったデータを使ってクライアント側でページを生成すると言う仕組みは共通していますので、ここに書いておきます。

 このホームページでは、サーバー側負荷を減らすための手段として AJAX を取り扱っています。サーバー負荷を減らすには「サーバー側のCPU処理量を少なくする」、「送出するデータ量を減らす」と言う点での改善が必要で、その為にサーバー側静的データ生成とクライアント側JavaScriptを利用しようとしています。この時コンテンツが動的では無い、つまり「リッチUI」を必要としない場合は、更なる軽減策が取れるのでは無いかと思われます。

 まずAJAXのページで例に挙げた様な、「ページリクエストに1回の http request, クライアントコンポーネントの必要なデータリクエストに10回の http request、クライアントはそのページを見るだけでリンククリック以外のアクションはしない」と言った様な状況を考えてみます。そこでは例え10回の http request であっても、静的に生成されたデータアクセスであればサーバー負荷は軽減されるとしていました。しかしそうは言っても、それが1回の http request にまで軽減されればより負荷が減るだろう事は容易に想像できると思います。それにはどうすれば良いか? HTML ファイルも XML 同様データコンテナです。そうすると、上記の「JSON in XML」で記したのと同じように、HTML に JSON データを運んでもらえば、最初のリクエストで全部送れるはずです。 これを簡単に示してみると下図の様になります。
サーバーサイドのみ
・DBクエリ1
・DBクエリ2
...
・DBクエリ10
・HTML生成
1回のHTTP接続
───────→
ブラウザで表示
AJAX+動的データ
・基本HTML
・DBクエリ1+データ生成1
・DBクエリ2+データ生成2

...

・DBクエリ10+データ生成10
11回のHTTP接続
───────→
ブラウザでHTML生成し表示
AJAX+静的データ
・基本HTML
・事前生成データ1
・事前生成データ2

...

・事前生成データ10
11回のHTTP接続
───────→
ブラウザでHTML生成し表示
(データ要求URLが違うだけで上記とコードは同じ)
HTML統合型
・基本HTML
・事前生成データ1
・事前生成データ2
...
・事前生成データ10
1回のHTTP接続
───────→
ブラウザでHTML生成し表示
(最初のデータ要求場所が違うだけで上記とコードは同じ)

 JSON データを HTML で送るとすればどんな風にするか? と考えて見ると、一番簡単に思いつくのは、

<script>
var data1 = { ←事前生成されたデータその1
 property_1:1,
 property_2:"日本語を含む utf-8 のデータ",
 property_3:[1,2,3],
 method_1:function() {
  alert("<タグはエスケープしなくても良し>");
 }
};
var data2 = { ←事前生成されたデータその2
 property_1:2,
 property_2:"日本語を含む utf-8 のデータ",
 property_3:[4,5,6],
};
...以下必要なだけ...
</script>

こんな形です。わざわざ言及するまでも無いくらいです。しかし、たくさんのクライアントコントロールが協調する事を考えると、あんまり大量にグローバル名前空間を使いたくはありません。とすると、

<script>
var generated_data = {
 data1:{ ←事前生成されたデータその1
  property_1:1,
  property_2:"日本語を含む utf-8 のデータ",
  property_3:[1,2,3],
  method_1:function() {
   alert("<タグはエスケープしなくても良し>");
  },
  data2:{ ←事前生成されたデータその2
  property_1:2,
  property_2:"日本語を含む utf-8 のデータ",
  property_3:[4,5,6],
 },
 ...以下必要なだけ...
 
};
</script>

な感じで良さそうです。

その他に、JavaScript の名前空間を使わない方法として、

<meta name="json" content="{
 property_1:1,,
 property_2:&quot;日本語を含む utf-8 のデータ&quot;,
 property_3:[1,2,3],
 method_1:function() {
  alert(&quot;&lt;タグはエスケープすれば良し&gt;&quot;);
 }
}">

と言う風に meta タグで送っておく方法も考えられます。クライアント側では、

var obj = eval('(' + document.all["json"].content +')');

で使用できます。

 事前生成データの作成方法によって使い方を選ぶと思いますが、やはり文字のエスケープの必要が無い2番目の方法が良さそうです。

クライアントコントロールのデータリクエスト方として、http://〜によるアクセスなら非同期データ取得、そうでなければ上記のオブジェクトから取得と言う風にしておけば、データコンテナに関係なくクライアントコントロールが使える様になって嬉しいでしょう。

HOME | LAJAXS | JSON | カレンダーコントロール
Copyright (C) 2005 Takashi Oyama All Rights Reserved.