在使用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到时候,从本质来说没有大的区别,这里不再赘述。