JSONPを使ってみた
JSONPとは、JSON with Paddingと言うことらしいですが、詳しい説明はググってください。
今回やりたいことは、別サーバにあるCSVファイルからパラメータで指定したidにマッチする値を取り出して表示する、というものです。
サーバ側のプログラムはPHPで作ってみました(経験値少ないので変なところがあるかも)。
元データになるuser.csvファイルはこんな感じです。
1,山田太郎 2,鈴木一郎 3,池田次郎
フィールドはidとnameになります。
次にサーバ側の処理です。
と、その前にPHP版のJSONライブラリと、JSONPで呼び出すためのJavaScriptライブラリを用意しておきます。
- PEAR::Services_JSON
- JSON and the Dynamic Script Tag: Easy, XML-less Web Services for JavaScript
- のjsr_class.js
サーバ側のindex.phpはこんな感じになります。UTF-8で保存しています。
<?php // JSON.phpを読み込む require_once('JSON.php'); // utf-8を使えるようにするおまじない setlocale(LC_ALL, 'ja_JP.UTF-8'); // callback関数名を取得 $cb = $_GET['callback']; // idを取得 $id = $_GET['id']; // CSVファイルをオープン $fp = fopen("user.csv", "r"); $user = array('name' => ''); while (($data = fgetcsv($fp, 1000, ",")) !== FALSE) { // $idにマッチする値を見つけた! if ($id == $data[0]) { $user = array('id' => $data[0], 'name' => $data[1]); break; } } // CSVファイルをクローズ fclose($fp); // Services_JSONオブジェクトを作成 $json = new Services_JSON; // レスポンスヘッダにContent-Typeを設定 header("Content-Type: text/javascript; charset=utf-8"); // JSON形式に変換して、callbackメソッドの引数として返す echo "$cb(" . $json->encode($user) . ")"; ?>
サーバ側のURLは、「http://example.com/index.php」とすると、次のようなURLをブラウザで開くことで、内容の確認が出来ます。
「http://example.com/index.php?id=1&callback=hello」
このレスポンスは、次のようになります。
hello({"id":"1","name":"\u5c71\u7530\u592a\u90ce"})
レスポンスの先頭の「hello」は、パラメータのcallbackで指定した文字が入ります。
例えば、http://example.com/index.php?id=1&callback=hogehogeで呼び出すと、次のようなレスポンスが返ってきます。
hogehgoe({"id":"1","name":"\u5c71\u7530\u592a\u90ce"})
という感じでブラウザで確認できたら、クライアント側のHTMLを書いてみましょう。
こんな感じです。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body> <span>JSONPを使うよ</span> <script type="text/javascript" src="http://example.com/jsr_class.js"> </script> <script type="text/javascript"> // callbackで呼び出される関数 function hello(data) { var resultData = ''; resultData += '<p>こんにちは ' + data.name + ' さん</p>'; document.getElementById('hellotarget').innerHTML = resultData; bObj.removeScriptTag(); } var req = 'http://example.com/index.php?id=1&callback=hello'; var bObj = new JSONscriptRequest(req); bObj.buildScriptTag(); bObj.addScriptTag(); </script> <div id="hellotarget" style="width:180px; border:thin #666666 solid;"></div> </body> </html>
JSONscriptRequestの引数で、サーバ側のスクリプトを呼び出します。
このレスポンスは、callbackで指定したJavaScriptの関数に対して、引数を設定した命令文として返ってきます。
この例では"hello"という関数を指定しているので、そのままfunction hello(data)が呼び出されます。
helloの中では、受け取った連想配列のnameの値を
<div id="hellotarget">
に挿入しています。
ただ、何も考えずに作るとCSRFの餌食になってしまうので、基本的には公開しても良いデータだけを扱うようにするべきでしょう。
さて、今回こんなことを調べる気になったのは、知人からの問い合わせでした。
その経緯はここでは書けませんが、良い勉強になったことは確かです。