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

在使用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到時候,從本質來說沒有大的區別,這裏不再贅述。


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