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

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

相关文章

AJAX是一种基于JavaScript和XML的技术,能够使网页实现异步交...
在网页开发中,我们常常需要通过Ajax从后端获取数据并在页面...
在前端开发中,经常需要循环JSON对象数组进行数据操作。使用...
AJAX(Asynchronous JavaScript and XML)是一种用于创建 We...
AJAX技术被广泛应用于现代Web开发,它可以在无需重新加载页面...
Ajax是一种通过JavaScript和HTTP请求交互的技术,可以实现无...