Timeオブジェクトに対するto_jsonメソッド呼び出し

Ajaxを多用したアプリケーションにおいても,Ruby on Railsの採用が今後どんどん増えていくと考えられる。Ajaxと言えば,言葉の通りXMLを連想するかもしれない。しかし,サーバから受け取った後の処理効率を考えると,JSONでやり取りを行ったほうがトータルで都合が良い。近年では,XMLではなくJSONを利用する機会が多いと考えられる。

Ruby on Railsの1.2から,全オブジェクトに対してto_jsonメソッドを呼び出すことができるようになった。これは,active_supportが提供してくれる機能である。例えば,

としてあげれば,”{name: \”Yoichiro\”, age: 32}”という結果を得ることができる。非常に便利である(速度に問題があるらしいけど)。

さて,これを書いている時点での最新であるRails 1.2.3では,to_jsonメソッドが全てにおいて万能かというと,残念ながらそうではない。実は,to_jsonメソッドを呼び出した結果を正しく受け取れるレシーバのクラスに制限があるのだ。これは,activesupport-1.4.2/lib/active_support/json/encodersディレクトリにあるcore.rbファイルの中身を見てみると良い。

正しく結果が得られるのは,TrueClass, FalseClass, NilClass, String, Numeric, Symbol, Enumerable, Hash, Regexpのみである。一般的なアプリケーションなら,これ以外にも多用しているクラスがあるはずだ。例えば,Timeクラスのオブジェクト。これはサポート外である。つまり,

としても,得られる結果は”{}”である。なんとも悲しい。

この問題は,RailsのTracにしっかりと登録されていて,既にパッチが提供されている(id:tonocchiさん,情報さんきゅです!)。このチケットがcloseになったのは,たった3ヶ月前。Railsの次のバージョンになればきっとTimeクラスに対するサポートも含まれることだろう。しかし,現状ではそのパッチをあてるか,動的になんとかするしかない。

Ticket #5140 (closed defect: fixed) – Rails Trac

というわけで,パッチをあてることなく,Timeクラスのオブジェクトに対してto_jsonメソッドが正しい結果を返すようにするコードが以下である。

先のcore.rbファイルでも使われているdefine_encoderメソッドを使って,自分でエンコード処理を追加登録している。上記のコードを,例えばapplication.rbファイルの中に書いておけば良いだろう。例えばHashオブジェクトの中にTimeクラスのオブジェクトがいるときにも,登録されたTimeクラスに対する処理(time.to_i.to_json)が実行され,日時を示す値がJSON文字列に格納されるようになる。

このテクニックはTimeクラスに限ったものではなく,ほかのクラスに関しても適用することができる。独自にJSON文字列の構築を処理したい場合などに活用すると良いだろう。

Trackback URL:

コメントを残す

コメントを投稿するにはログインしてください。

Get Adobe Flash playerPlugin by wpburn.com wordpress themes