at posts/single.html

JSON + prototype.js

prototype.js1.4.0 (正確にはもう少し前) で JSON がサポートされたので、試しに使ってみる。 2nd life - prototype.js 1.4.0 pre6 でのJSONサポートによると、 サーバからのレスポンスの X-JSON ヘッダに含まれる文字列をオブジェクトに変換してくれるものらしい。

早速、サンプルを作ってみた。

<html lang="ja-JP">
 <head>
   <script type="text/javascript" src="prototype.js"></script>
   <title>JSON Test</title>
   <script type="text/javascript">
     function update() {
       url = 'ajax.cgi';
       options = { onComplete: complete };
       new Ajax.Request(url, options);
     }
     function complete(req, json) {
       alert(json.name);
       $('debug').value = req.responseText;
     }
   </script>
 </head>
 <body>
   <button id="test">test</button><br>
   <textarea id="debug" rows="100" cols="100"></textarea>
 </body>
</html>

JSON から変換されたオブジェクトは、 onComplete の引数 json として渡される。

サーバ側のサンプルコードはこの通り。ヘッダに X-JSON を追加している。

#!/usr/local/bin/ruby
require 'cgi'

cgi = CGI.new
puts cgi.header({'X-JSON', '({"name": "Mr. Smith"})'})
puts '<div>this is a sample</div>'

先ほどの html ファイルをブラウザで開き、 test ボタンを押すとダイアログに「Mr. Smith」と表示される。簡単簡単。 responseText に HTML の断片を入れて、 JSON でそれ以外のデータを送る用途に向いてそう。ちょうど今、そういう仕組みが欲しいところだった。

落とし穴

簡単といいつつ、落とし穴ではまった。 サーバからのレスポンスは、括弧で括る必要がある。 これが分からずに、しばらく悩んでいた。

○ puts cgi.header({'X-JSON', '({"name": "Mr. Smith"})'})
× puts cgi.header({'X-JSON', '{"name": "Mr. Smith"}'})

参考になったページは、JSON in JavaScriptとか、その日本語訳とか。 prototype.js の内部で eval を使って変換しているんだけど、この eval には「式」を渡さないといけないらしい。 括弧で括ると式になるのね。

おまけ

このサンプルでも動かない…動かないと思っていたら、 読み込んでいた prototype.js のバージョンが古かった (1.4.0 pre4) というオチが(30分ほど悩んでいた)。

関連リンク

関連する日記