接口实现
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();
}
代码不是非常复杂,因此请读者自行阅读。