【引言】最近才接触到org.json,他比较小巧没有依赖包用起来还不错,不足的是没有一个JSONObject对象直接转JavaBean的方法。为了弥补这个缺憾,自己在源码中(org.java.JSONObject.java)加了一个这样的方法,这里分享一下。
昨天才知道Android系统里也有一个org.json,它里面没有JSONObject(Object bean)方法。推荐看看https://github.com/douglascrockford/JSON-java这里的源码,比Android自带的org.json功能多一点。
在JSONObject中,用了一个域
private final Map<String, Object>map;
如果一个JSONObject是由Bean转换来的,那么Bean中所有的域都被妥善存放在map中。构造函数
public JSONObject(Object bean) {
this();
this.populateMap(bean);
}
就是用来干这个事情的。遗憾的是并没有一个反向的方法从JSONObctive对象生成Bean对象。观察源码中populateMap(bean)方法的实现,可以看到:他是用反射实现对Bean中getter的调用。所以反过来我们遍历Map,然后用反射调用setter就能达到目标。
从Bean中找出所有的域
Method[]beanMethods = javaBeanClazz.getDeclaredMethods();
从Bean中找出所有的域
for (Methodmethod :beanMethods)
{
if (method.getName().startsWith("set"))
{。。。
}
}
反射调用setter method.invoke(javaBean,newObject[] {map.get(field)});
方法定义的时候得耍几个小技巧
首先,populateMap方法的参数是个对象,而我们实现JSONToBean的时候,只想通过方法返回一个Bean对象,入参只说明Bean对象的Class。
其次,入参和返回值都是相同的Class,自然想到使用泛型。需要注意的是,只有泛型是无法实例化的,需要用该泛型指定一个Class对象。
所以,方法的声明看起来像这样:
public <T> TtoJavaBean(Class<T> javaBeanClazz)
【caution】
Bean中不能有Date对象这种没法串行化的域,毕竟我们是在接收端用String生成的JSONObject,Date.toString()出来的东西没法反向生成Date,想必大家都知道。
【调用】假如你有一个Bean类叫Book,然后你从服务端收到一个jsonString,现在可以直接转出Book对象
JSONObject jObject = new JSONObject(jsonString);
Book resultBook = jObject.toJavaBean(Book.class);
【代码】最后贴出完整代码,欢迎各种拍砖。
/** * change the JSONObject to Bean * * @author Y.T * @param javaBeanClazz * indicate target class * @return JavaBean * @throws JSONException * any error happened during transform */ public <T> T toJavaBean(Class<T> javaBeanClazz) throws JSONException { Method[] beanMethods = javaBeanClazz.getDeclaredMethods(); T javaBean = null; try { javaBean = javaBeanClazz.newInstance(); } catch (Exception e){ throw new JSONException("Can not create a instance of Class " + javaBeanClazz.getName() + "."); } for (Method method : beanMethods) { if (method.getName().startsWith("set")) { String field = method.getName(); field = field.substring(field.indexOf("set") + 3); field = field.toLowerCase().charAt(0) + field.substring(1); //ignore the null value exception, add by y.t. 2015.03.10 if (map.get(field)==null) { continue; } try { method.invoke(javaBean, new Object[] {map.get(field)}); } catch (Exception e) { // TODO Auto-generated catch block throw new JSONException("Can not find property" + " setter for field \"" + field + "\" in Class \"" + javaBeanClazz.getName() + "\"."); } } } return javaBean; }