Playing with Play: Json POJO binding
13. Oktober 2011
Since I am used to the handy and easy way of binding HTTP requests parameters to POJOs in Spring I despredly searched for a possibilities to do that in play! It is possible by default for JPA like parameters like obj[1].key=value&obj[2].key=value, but not for json objects. Since Gson is very handy and powerful in parsing json to POJOs I decided to extend play by that functionality.
For this I needed to write a PlayPlugin, since play is treating HTTP parameters based on the naming convention key=value, where key matches the controller parameter name (which btw. is not accessible with Java Reflection, but with a own crafted Java.parameterNames(Method) byte code parser, which only works when play compiles and controls the classes), as a JPA Model object, which is then converted to an empty POJO by the JPAPlugin, and so returned to the Controller method. In order to prevent that I needed to sneak between the other data binding plugins in order to convert the params.
My work is based on this stackoverflow answer. First you place a play.plugins file in your application conf directory with a line like: 101:controllers.JsonDataBindingPlugin, where 101 is the plugin id which is pretty at the beginning of the data binding chain then you extend the PlayPlugin class like that:
package controllers;
import play.PlayPlugin;
...
public class JsonDataBindingPlugin extends PlayPlugin {
private Gson gson;
// 101:controllers.JsonDataBindingPlugin
private Gson getGson() {
if (gson == null) {
gson = new Gson();
}
return gson;
}
@Override
public Object bind(String name, Class clazz, Type type,
Annotation[] annotations, Map<String, String[]> params) {
if (params.containsKey(name)) {
String[] strings = params.get(name);
if (strings.length == 1) {
String param = strings[0];
if (param.startsWith("{")) {
try {
Object fromJson = getGson().fromJson(param, type);
return fromJson;
} catch (JsonSyntaxException e) {
return null;
}
}
}
}
return super.bind(name, clazz, type, annotations, params);
}
}