在使用JSONObject和JSONArray的過程中,往往讓人驚歎它的神奇之處,能夠很方面的把json對象和bean互相轉換,一直在思考究竟後臺如何實現的,雖然通過看源碼可以得出答案,但畢竟源碼過於繁複,短時間內難以盡解,不如自己思考:如果這個功能是我設計的,我會怎麼實現呢?其實無非就是使用反射而已,加上循環和迭代,把集合類型和嵌套的對象都迭代出來。
被序列化的類詳見:http://blog.csdn.net/salerzhang/article/details/41259471
初始化一個對象:
<span style="white-space:pre"> </span>Student student = new Student();
student.setName("zxl");
student.setGerder("M");
//student.setAddress("beijing");
Classes cs = new Classes();
cs.setClaName("計算機1");
cs.setClsNum("07060341");
cs.setWay("wentaoyuan1");
List<Student> list = new ArrayList<Student>();
list.add(student);
cs.setStudents(list);
cs.setStudent(student);
被反序列化的數據:
JSONObject jo = JSONObject.fromObject("{'clsNum':'123','claName':'計算機2','student':{'gerder':'F','name':'zxl'},'students':[{'address':'shanghai','gerder':'M','name':'xxx'}],'way':'wentaoyuan1'}");
JsonConfig:
Map<String, Class<?>> clazz = new HashMap<String, Class<?>>();
clazz.put("student", Student.class);
clazz.put("students", Student.class);
JsonConfig jc = new JsonConfig();
jc.setClassMap(clazz);
private static Object jsonObjectIterator(Object root, JSONObject jo, JsonConfig jc) throws InstantiationException,
IllegalAccessException, ClassNotFoundException, SecurityException, NoSuchMethodException,
IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
Iterator<String> keys = jo.keys();
Map<String, Class<?>> clazz = jc.getClassMap();
while (keys.hasNext()) {
String key = (String) keys.next();
if (jo.get(key) instanceof JSONObject) {//嵌套對象
Object o = Class.forName(clazz.get(key).getName()).newInstance();
String setMethodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
o = jsonObjectIterator(o, jo.getJSONObject(key), jc);
Method setMethod = root.getClass().getMethod(setMethodName, clazz.get(key));
setMethod.invoke(root, o);
} else if (jo.get(key) instanceof JSONArray) {//嵌套數組
JSONArray ja = jo.getJSONArray(key);
List<Object> list = new ArrayList<Object>();
Method method = list.getClass().getMethod("add", Object.class);
for (int i = 0; i < ja.size(); i++) {
Object o = Class.forName(clazz.get(key).getName()).newInstance();
jsonObjectIterator(o, ja.getJSONObject(i), jc);
method.invoke(list, o);
}
String setMethodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
Method setMethod = root.getClass().getMethod(setMethodName, List.class);
setMethod.invoke(root, list);
} else {//本級屬性
Field field = root.getClass().getDeclaredField(key);
if (field.getName().equals(key)) {
Type type = field.getGenericType();
String fieldName = key.substring(0, 1).toUpperCase() + key.substring(1);
setObjectByString(root, jo.getString(key), fieldName, type);
}
}
}
// root = setObjectByJson(root, jo, false);
return root;
}
該方法需要配置三個參數:
* @param root 主類對象 注意參數是對象而不是類的Class
* @param jo 被反序列化的內容 需要轉換成JSONObject再傳入
* @param jc classMap 包括classMap的配置等
該方法等的大概邏輯:
遍歷JSONObject對象,分三個邏輯處理:
1,屬性:按類型處理,不同類型的參數要進行轉換,使用方法:
private static void setObjectByString(Object o, String valueFromJson, String name, Type type)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
String t = type.toString();
if (t.equals("class java.lang.String")) { // 如果type是類類型,則前面包含"class ",後面跟類名
Method m = o.getClass().getMethod("get" + name);
String value = (String) m.invoke(o); // 調用getter方法獲取屬性值
// if (value == null) {
m = o.getClass().getMethod("set" + name, String.class);
m.invoke(o, valueFromJson);
// }
}
if (t.equals("class java.lang.Integer")) {
Method m = o.getClass().getMethod("get" + name);
Integer value = (Integer) m.invoke(o);
if (value == null) {
m = o.getClass().getMethod("set" + name, Integer.class);
m.invoke(o, StringParseUtil.parse2Integer(valueFromJson));
}
}
if (t.equals("class java.lang.Boolean")) {
Method m = o.getClass().getMethod("get" + name);
Boolean value = (Boolean) m.invoke(o);
if (value == null) {
m = o.getClass().getMethod("set" + name, Boolean.class);
m.invoke(o, StringParseUtil.parse2Boolean(valueFromJson));
}
}
if (t.equals("class java.util.Date")) {
Method m = o.getClass().getMethod("get" + name);
Date value = (Date) m.invoke(o);
if (value == null) {
m = o.getClass().getMethod("set" + name, Date.class);
m.invoke(o, StringParseUtil.parse2Date(valueFromJson));
}
}
}
2,JSONObject類型,獲取類型迭代
注意:要找到嵌套類的類路徑,這個在ClassMap中,迭代完成後,需要把嵌套對象放進主類對象中。
3,JSONArray類型,先遍歷數組,然後迭代
注意:要判斷集合的類型,本例中只默認使用List類型,在獲取setter方法時,一定要傳入集合的的類型,這個類型要與聲明的集合類一致(不是實際類型),比如:Classes對象中有一個集合類型的成員變量:private List<Student> students; List是一個接口,在實例化的時候,很可能是ArrayList對象,但這裏我們只能用List.class標識setter方法的參數類型,而不能用ArrayList.class。
當集合類型是Map或Set到時候,從本質來說沒有大的區別,這裏不再贅述。