あどけない話

Internet technologies

JSONP

今日は、JSONP のお話です。昨日の JSON の話を読んでいない人は、まずそちらから読んで下さいね。

JSONPJSON with Padding の略称であり、 Bob Ippolito さんがRemote JSON - JSONPという記事の中で提唱しました。

ここでいう Padding とは、JSON データに関数名を付加することです。もっと詳しく言うと、サーバがブラウザに JSON データを送る際に、ブラウザが指定した JavaScript の関数名を付加することです。

なぜ、JSON に関数名を付加するの必要があるのでしょうか? それを理解すれば、JSONP が分ったことになります。

よくあるストーリー

ブラウザがサーバと通信しており、そのデータ形式JSON を使っている状況を考えてみて下さい。たとえば、ブラウザから youtube に、あるキーワードで検索をかけ、youtube からマッチしたビデオの情報が JSON 形式で返ってくるような場合を思い描いて下さい。

ブラウザは、その JSON を引数にして定義してある関数を呼び出し、JSON データを処理します。上記の例であれば、ビデオの一覧を表示します。

実は、こんな簡単なことが、JavaScript ではできないのです!

JavaScript の制約

ブラウザから youtube に検索をかけるといいましたが、その検索のページは、youtube とは関係ないサーバにあるとしましょう。たとえば、あなたのプログのページに、youtube の検索窓がある場合を考えてみて下さい。

ここでの登場人物は、3人になります。

  • ブラウザ
  • 検索窓のあるページを置いてあるブログのサーバ
  • youtube のサーバ

ブラウザは、ブログのサーバから HTML ファイルをダウンロードして、そこに記述されている JavaScript のコードを実行することになります。セキュリティ上の問題から、JavaScript が(XMLHttpRequest を使って)通信できる相手は、ブログのサーバだけです。

なので、youtube のサーバに問い合わせたり、ましてや返ってきた JSON データを処理したりなんてできないのです!

サイトを越える

他のサーバと通信するためには、HTML の script タグを活用します。

JavaScript は、以下のように HTML の script タグに書くのでした。

<script>
// 関数定義
function displayVideos(json) {
    // ビデオを表示する
}
// 関数呼び出し
displayVideos({"title": "Kind Lines", "id": "74830"});
</script>

script タグは、複数書けます。

<script>
// 関数定義
function displayVideos(json) {
    // ビデオを表示する
}
</script>
<script>
// 関数呼び出し
displayVideos({"title": "Kind Lines", "id": "74830"});
</script>

JavaScript を別ファイル foo.js に移すとこうなります。

<script>
// 関数定義
function displayVideos(json) {
    // ビデオを表示する
}
</script>
<script src="foo.js"></script>

属性である src には URL を指定できます。そのため foo.js は、ブログのサーバではなく、他のサーバにあってもよいのです。これで、サイトを越えられます。

youtube などでは、パラメータとして、URL のファイル名にあたるところに、検索のためのキーワードを書くことができます。そのパラメータを含んだ URL へアクセスすると、検索できます。

script タグの src 属性に、このパラメータを含んだ URL を書いておけば、ブラウザはその URL にアクセスしますから、youtube を検索することができるのです。

youtube からの応答は、JavaScript のコードとして処理されます。

youtube から単なる JSON データが返ってくる場合、それが評価(データが定義)されて、終わってしまいます。何も起きません。もし、youtube が、関数名 displayVideos を付加した(パディングした)データを返してくれたらどうなるでしょうか?

displayVideos({"title": "Kind Lines", "id": "74830"});

当然、displayVideos が JSON データとともに呼び出されて、めでたくビデオの一覧が表示されます。

youtube は、この関数名を知るため callback というパラメータを用意しています。ブラウザは、検索キーワードに加えて、"callback=displayVideo" のように実行したい関数名を指定するのです。

ユーザの検索

静的に script タグと src 属性が書かれているなら、ユーザが検索するキーワードを入力する方法がありません。

実は、script タグは JavaScript によって、動的に生成されます。ユーザがキーワードを入力すると、JavaScript で書いたコードが、パラメータを含んだ URL を src 属性に指定した script タグを作成し、HTML のヘッダに挿入するのです。

そうすると、ブラウザはサーバにアクセスして検索し、検索結果を JavaScript のコードだと思って実行するので、めでたくビデオが一覧表示される訳です。

これが JSONP の仕組みです。理解できましたか?