使用反射自定义序列化方法

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章