2006年08月27日

JSONでなくてJSONP[JSON with Padding](クロスドメイン解決)


JSON(JavaScript Object Notation)ってのは、Javascipt扱う人ならば大体知っていると思う。
簡単に言えば、JavaScript のデータ互換フォーマットの事。
{
"hoge": 1,
"fuga": ["a", "b", "c"]
}
みたいなフォーマット。
参考)
Collection & Copy - [翻訳]JSON入門
JavaScript++かも日記 - JSON/簡単なテスト:基本

これは確かに、同一ドメインでクライアントに渡すデータとしては有効で、レスポンスをそのまま eval して使えるので便利なのだ。(prototype.js では Ajax.Request.prototype.evalJSON() を利用すれば JavaScript のオブジェクトになる)

ただ、JavsScript ではセキュリティの問題でクロスドメインでのデータ通信は制限されているのは周知のとおりで、自分でサーバースクリプトを触れないと利用できない。
そのため、様々な解決方法が考えられているが、最近の流行は JSONP って方法だ。
(この「JavaScriptのクロスドメインはセキュリティの問題」ってのがバズワード化しているようにも思える。XmlHttpRequestでクロスドメインのデータ使うのと、他の手段を使ってクロスサイトのスクリプト読み込むのとで、根本的にセキュリティの穴の違いってあるの?結局、不特定多数がスクリプト仕込めるような環境だと、同じに思えるんだけれども!同じなら、制限なくなればいいのにと思ったり。誰か決定的な違いがあるって知ってたら教えてください)

簡単に説明すると以下のようになる。
1) JavaScript のインポートは XmlHttpRequest と違い、同一ドメインでなくても読み込めるという点を利用する。
var script = document.createElement('script');
script.charset = 'utf-8';
script.src = url; // 同一ドメインでなくても良い
document.body.appendChild(script);

2)レスポンスは JavaScript として動けばそれでよいので
var data = {"prop1": "serverdata"}
などを返す事により、var data を利用する。

ただ、問題なのはインポートは非同期なので、すぐ後に
alert(data.prop1);
などと書いても、undefined となってしまう。そのために、読み込み完了を通知する為の callback を指定するという方法だ。どんな方法でも良いのだが、例えば
if (typeof data == 'undefined') var data = {};
data = {"prop1": "serverdata"};
if (typeof(data.onload) == 'function') data.onload(data);
などとしてレスポンスを実装したりする。
他にも、単純に
calbackfunc({"data": {"prop1": "serverdata"}})
などのレスポンスでも良い。

現在、webで有名なサービスも続々と JSONP を提供してくれてる。
(Google, Amazon, del.icio.us, Flickr等)
XMLをJSONにしてくれるdrk7.jpさんのサービスもそうなのだが、XMLにエラーがあると、JSONPでなくJSONになるのが困る。
参考)
snippets from shinichitomita’s journal - ブラウザからJSONで呼び出せるサービス一覧

もっと詳しい説明は、以下の参考記事を見てくれ!
とりあえず、Hatena も API や Feed だけじゃなく JSONP 提供してくれねーかなぁって感じ。


* 参考記事
from __future__ import * » Remote JSON - JSONP
ITmedia エンタープライズ:実は、Ajaxのウラにこそ勝算がある (1/5)
hail2u.net - Weblog - JSONScriptRequest
hail2u.net - Weblog - JSONP
JavaScript++かも日記: 【JSON】Remote JSON - JSONP
JXML を JSON に変換するサービス - ベータ版を公開 :: Drk7jp
posted by suVene at 16:44