JSONIC+Slim3+DatastoreでUnsupportedOperationExceptionが出るときの回避方法
エンティティクラスに com.google.appengine.api.datatore.Text型を使ったプロパティを追加したら、クライアント側からJSONを送信した時に、JSONICがUnsupportedOperationExceptionってのを出すようになった。
JSONICがDatastoreのText型なんて知らねーよ、ってことらしい。
JSONICのドキュメントを調べてみたら、このあたりに書いてあることをやればいいらしい。
≫JSONIC - simple json encoder/decoder for java
というわけで、JSON4Gaeってクラスを作る。パッケージは com.satoshis ってことで。
package com.satoshis; import net.arnx.jsonic.JSON; public class JSON4Gae extends JSON { }
JSONをエンティティに変換するときに呼ばれるのが postparse()メソッドらしいので、それをオーバーライドしてやる。
まずは、コンソールに引数の内容を出力して、どんな引数で呼ばれているのかを確認する。
public class JSON4Gae extends JSON { @Override protected <T> T postparse(Context context, Object value, Class<? extends T> c, Type t) throws Exception { System.out.println("Context=" + context + ", value=" + value + ", Class=" + c + ", Type=" + t); return super.postparse(context, value, c, t); } }
でも、クラスを作ってメソッドをオーバーライドしただけじゃ、このクラスを呼び出してくれない。デフォルトのJSONクラスを呼び出す代わりに、このクラスを呼び出すようにするために、web.xmlを修正する。processorで、自作したクラス名を書けばいいらしい。
<servlet> <servlet-name>RestServlet</servlet-name> <servlet-class>net.arnx.jsonic.web.RESTServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value> { "debug": true, "mappings": {"/json/{class}.json": "com.aetalog.controller.json.${class}Controller"}, "processor": "com.satoshis.JSON4Gae" } </param-value> </init-param> </servlet>
サーバーを再起動して実行すると、Text型に指定したメンバ名がhogeならば、こんな感じの出力。
Context=$.hoge[null][null], value=abcdefg, Class=class com.google.appengine.api.datastore.Text, Type=class com.google.appengine.api.datastore.Text
valueの型を調べたらStringだった(当然)。
つまり、StringをTextに変換する方法がわからんってことなので、その実装を追加してやる。
public class JSON4Gae extends JSON { @Override protected <T> T postparse(Context context, Object value, Class<? extends T> c, Type t) throws Exception { if (Text.class.isAssignableFrom(c) && value instanceof String) { Text text = new Text((String)value); return c.cast(text); } return super.postparse(context, value, c, t); } }
これで動いた。