8.4 接口实现 8.4.1 json2Obj 实现 根据需求分析中JSON 到Java对象的数据转换规则,json2Obj 方法的输入参数jsonStr,可能为以下几种情况: (1)单值,如“abcd”。 (2)值序列,如 [1, 2, 5, 9]。 (3)名值对,如 { x : 10, y : 25}。 (4)嵌套,如 {leftUpper: [20,50], rightDown: [200, 450]}。 因此,json2Obj函数,首先要将JSON 字符串分解为一系列属性。这里属性的含义,可以代表一个最基本的名值对,也可以代表单值。 属性分解完毕后,接着就要分析目标对象的类型。目标对象可能为如下情况之一: (1)Java内置类型:直接将JSON串分解后的属性转换为Java内置类型即可; (2)数组:对每个属性递归调用json2Obj,返回的对象设置到数组的相应元素位置上; (3)集合类型:对每个属性递归调用json2Obj,返回的对象添加到相应的集合中; (4)Map:对每个属性递归调用json2Obj,返回的对象作为Value,属性名作为Key,添加到Map中; (5)用户自定义对象:用反射技术解析对象的各个属性,对每个JSON串解析出的各个属性,调用json2Obj,将返回的对象设置到Java对象相应的属性上。 核心代码实现如下: /** * 将Json 串转换为Java对象 * @param jsonStr 待转换的Json串,可以是内置类型、数组或者对象, * 也可以是上述三种的任意组合 * @param cls 目标Java对象的类 * @return 返回转换后的Java对象,可能是内置类型、数组、集合类型或者对象 * @exception 如果转换过程出现异常,统一抛出GeneralException 异常 */ public static <T> T json2Obj(String jsonStr, Class<T> cls) { // 1. 如果是内置类型,则直接进行数据类型转换即可 String objTypeName = cls.getName(); int objType = DataType.getDataType(objTypeName); if (DataType.isSimpleType(objType)) { // 简单类型 jsonStr = jsonStr.trim(); jsonStr = delQuote(jsonStr); // 去掉引号 return (T)DataType.toType(jsonStr, DataType.DT_String, objType); }
// 2. 解析jsonStr, 切出各个属性 // 2.1 合并成单行 jsonStr = jsonStr.replace("\n", ""); //jsonStr = jsonStr.replace("\t", ""); jsonStr = jsonStr.trim(); // 2.2 分解出各个属性 List<JsonProp> propList = splitProperties(jsonStr);
// 3. 创建目标对象 Object obj = null; switch (objType) { case DataType.DT_Array: // 数组的创建需要知道数组元素的类型和数组长度,因此后续再创建 break; case DataType.DT_List: obj = ClassReflector.newInstance("java.util.ArrayList"); break; case DataType.DT_Set: obj = ClassReflector.newInstance("java.util.HashSet"); break; case DataType.DT_Map: obj = ClassReflector.newInstance("java.util.Hashtable"); break; default: obj = ClassReflector.newInstance(cls); }
// 4. 处理对象的场景 if (objType == DataType.DT_UserDefine) { // 对象 ClassReflector reflector = new ClassReflector(obj); // 逐个属性向obj 赋值 for (JsonProp p : propList) { String propTypeName = reflector.getPropertyType(p.propName); Object propObj = json2Obj(p.jsonPropValue, propTypeName); reflector.setPropertyValue(p.propName, propObj); } return (T)obj; }
// 5. 处理数组/集合的场景 // 5.1 获取元素的类型 String elementTypeName = DataType.getElementTypeName(objTypeName); Class elementCls = ClassReflector.newClass(elementTypeName); int index = 0; // 5.2 解析每个元素对象,放入数组或集合中 for (JsonProp p : propList) { // 5.2.1 解析每个元素对象 Object elementObj = json2Obj(p.jsonPropValue, elementCls);
// 5.2.2 将元素对象放入数组或集合中 switch(objType) { case DataType.DT_Array: if (obj == null) { obj = ClassReflector.newArray(elementCls, propList.size()); } ClassReflector.setArrayElement(obj, index++, elementObj); break; case DataType.DT_List: ((List)obj).add(elementObj); break; case DataType.DT_Map: ((Map)obj).put(p.propName, elementObj); break; case DataType.DT_Set: ((Set)obj).add(elementObj); break; } }
// 返回转换后的集合对象 return (T)obj; } json2Obj 方法实现过程,主要步骤如下: (1)如果目标Java类是内置类型,则直接进行数据类型转换即可,转换结束; (2)将JSON串分解为一系列属性结构,每个属性结构用JsonProp 表示; (3)生成目标Java类的对象实例; (4)如果目标Java类是自定义对象类型,则对每个JsonProp结构,递归调用json2Obj 方法,将返回的对象设置到目标对象实例相应的属性上,返回目标对象,转换结束; (5)对数组和集合类型,单独进行处理。这种情况下,需要获取数组或集合内的元素类型,根据元素类型构建相应的元素,然后再放入数组或者集合。 在实现过程,大量使用了递归。 JSON串分解后的每个属性结构,用JsonProp 来表示,定义如下: package ticd.java.component.json; public class JsonProp { public static final int SIMPLE = 0; public static final int ARRAY = 1; public static final int OBJECT = 2;
public JsonProp(String propName, int propType, String jsonPropValue) { this.propName = propName; this.propType = propType; this.jsonPropValue = jsonPropValue; }
public String propName; public int propType; public String jsonPropValue; } 将JSON串分解为一系列JsonProp结构,是由splitProperties() 函数完成的,请读者自行阅读代码。 8.4.2 obj2Json 实现 理解了json2Obj() 方法的实现,再来看obj2Json() 方法,就容易多了。obj2Json() 方法的实现思路,与json2Obj() 方法类似。obj2Json() 方法将Java对象转换为JSON格式的字符串。Java对象可能为如下情况之一: (1)内置类型:如String, Integer, Date等。 (2)数组:如int[], String[][]等。 (3)集合:如List、Set。 (4)Map。 (5)自定义对象。 (6)以上各种组合:如自定义对象构成的数组。 因此,在实现上,也是递归调用obj2Json方法,直到最基本的类型被转换为Json串。核心代码如下: /** * 将Java对象转换为JSON字符串 * @param obj 待转换的Java对象 * @return 返回转换后的JSON字符串 */ public static String obj2Json(Object obj) { int objDataType = DataType.getDataType(obj); if (DataType.isSimpleType(objDataType)) { switch (objDataType) { case DataType.DT_Character: case DataType.DT_String: case DataType.DT_Date: case DataType.DT_Time: case DataType.DT_DateTime: obj = DataType.toType(obj, objDataType, DataType.DT_String); return "\"" + obj.toString() + "\""; default: return obj.toString(); } }
// 处理复杂类型 StringBuilder sb = new StringBuilder(); switch (objDataType) { case DataType.DT_Array: sb.append('['); int iLen = Array.getLength(obj); for (int i = 0; i < iLen; i++) { sb.append(obj2Json(Array.get(obj, i))); sb.append(", "); } sb.delete(sb.length() - 2, sb.length()); sb.append(']'); break; case DataType.DT_List: sb.append('['); List list = (List)obj; for (Object o : list) { sb.append(obj2Json(o)); sb.append(", "); } sb.delete(sb.length() - 2, sb.length()); sb.append(']'); break; case DataType.DT_Set: sb.append('['); Set set = (Set)obj; Iterator it = set.iterator(); while (it.hasNext()) { sb.append(obj2Json(it.next())); sb.append(", "); } sb.delete(sb.length() - 2, sb.length()); sb.append(']'); break; case DataType.DT_Map: sb.append("{"); Set entrySet = ((Map)obj).entrySet(); Iterator iterator = entrySet.iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry)iterator.next(); Object key = entry.getKey(); sb.append(key.toString()); sb.append(" : ");
Object value = entry.getValue(); sb.append(obj2Json(value)); sb.append(", "); } sb.delete(sb.length() - 2, sb.length()); sb.append("}"); break; case DataType.DT_UserDefine: sb.append("{"); ClassReflector reflector = new ClassReflector(obj); int iCount = reflector.getPropertyCount(); for (int i = 0; i < iCount; i++) { String propName = reflector.getPropertyName(i); sb.append(propName); sb.append(" : ");
Object propValue = reflector.getPropertyValue(i); sb.append(obj2Json(propValue)); sb.append(",\n"); } sb.delete(sb.length() - 2, sb.length()); sb.append("}"); break; default: return obj.toString(); }
return sb.toString(); } 代码不是非常复杂,因此请读者自行阅读。 |
|