json-lib反序列化抽象属性及对象
使用json默认反序列化接口反序列化对象时,对象的类型必须的确定的,比如不能是抽象类型,否则会报无法实例化对象的异常
如有下列类定义:
1 public abstract class AbstracObj { 2 3 private String propCommmon; 4 5 public String getPropCommmon() { 6 return propCommmon; 7 } 8 9 public void setPropCommmon(String propCommmon) { 10 this.propCommmon = propCommmon; 11 } 12 13 }
1 public class ObjectA extends AbstracObj{ 2 3 private String propA; 4 5 public String getPropA() { 6 return propA; 7 } 8 9 public void setPropA(String propA) { 10 this.propA = propA; 11 } 12 13 }
1 public class ObjectB extends AbstracObj{ 2 3 private String propB; 4 5 public String getPropB() { 6 return propB; 7 } 8 9 public void setPropB(String propB) { 10 this.propB = propB; 11 } 12 13 }
1 import net.sf.json.JSONObject; 2 3 public class TestJsonObj { 4 5 private String jsonProp; 6 7 private AbstracObj absProp; 8 9 public String getJsonProp() { 10 return jsonProp; 11 } 12 13 public void setJsonProp(String jsonProp) { 14 this.jsonProp = jsonProp; 15 } 16 17 public AbstracObj getAbsProp() { 18 return absProp; 19 } 20 21 public void setAbsProp(AbstracObj absProp) { 22 this.absProp = absProp; 23 } 24 25 public static void main(String[] args) { 26 TestJsonObj tb = new TestJsonObj(); 27 tb.setJsonProp("aaaa"); 28 ObjectA oa = new ObjectA(); 29 oa.setPropCommmon("common"); 30 oa.setPropA("propA"); 31 tb.setAbsProp(oa); 32 JSONObject jsonObject = JSONObject.fromObject(tb); 33 jsonObject.toBean(jsonObject, TestJsonObj.class); 34 } 35 }
TestJsonObj无法反序列化,因为它有一个抽象属性absProp。
可以通过增加标志抽象对象的类型属性及重载json-lib反序列化的接口实现。
定义接口Jsonable,让对象实现这个接口:
1 public class ObjectA extends AbstracObj implements Jsonable { 2 3 private String propA; 4 5 public String getPropA() { 6 return propA; 7 } 8 9 public void setPropA(String propA) { 10 this.propA = propA; 11 } 12 13 @Override 14 public Class<?> getClazz() { 15 return ObjectA.class; 16 } 17 18 }
1 public class ObjectB extends AbstracObj implements Jsonable { 2 3 private String propB; 4 5 public String getPropB() { 6 return propB; 7 } 8 9 public void setPropB(String propB) { 10 this.propB = propB; 11 } 12 13 @Override 14 public Class<?> getClazz() { 15 return ObjectB.class; 16 } 17 18 }
1 package com.mucfc.mpf.utils; 2 3 import java.lang.reflect.Array; 4 import java.lang.reflect.InvocationTargetException; 5 import java.lang.reflect.Modifier; 6 import java.util.List; 7 8 import net.sf.json.JSONArray; 9 import net.sf.json.JSONObject; 10 import net.sf.json.JsonConfig; 11 import net.sf.json.util.JSONTokener; 12 import net.sf.json.util.NewBeanInstanceStrategy; 13 14 import com.lz.lsf.exception.ServiceException; 15 import com.lz.lsf.exception.SystemException; 16 import com.mucfc.mpf.common.exception.MpfErrorCode; 17 18 /** 19 * json序列化反序列化帮助类 20 * 21 * @author hebeisheng 22 * @Since 2015/7/1 23 * 24 */ 25 public class JsonUtil { 26 27 private static JsonConfig unserializableConfig = new JsonConfig(); 28 29 static { 30 // 设置类初始化策略,过滤抽象类 31 unserializableConfig.setNewBeanInstanceStrategy(new NewBeanInstanceStrategy() { 32 33 @Override 34 public Object newInstance(Class c, JSONObject jo) throws InstantiationException, IllegalAccessException, 35 SecurityException, NoSuchMethodException, InvocationTargetException { 36 // 是否为抽象类 37 if (Modifier.isAbstract(c.getModifiers())) { 38 try { 39 // 返回类 40 return Class.forName(jo.getString("clazz")).newInstance(); 41 } 42 catch (Exception e) { 43 e.printStackTrace(); 44 } 45 } 46 return c.newInstance(); 47 } 48 }); 49 } 50 51 /** 52 * 将对象转成Json字符串 53 * 54 * @param object 55 * 对象 56 * @return 返回 Json字符串 57 */ 58 public static String toJson(Object object) { 59 if (List.class.isAssignableFrom(object.getClass())) { 60 JSONArray array = JSONArray.fromObject(object); 61 return array.toString(); 62 } 63 JSONObject jsonObject = JSONObject.fromObject(object); 64 return jsonObject.toString(); 65 } 66 67 /** 68 * 将json字符串反序列化成对象.</p> 69 * 70 * 如果传下来classType的值,则反序列了classType,如果没有传,则json串中必须含有clazz属性,指定json串要反序列化的类型。 71 * 72 * @param json 73 * json字符串 74 * @return 返回对象 75 */ 76 public static Object toObject(String json, Class<?> classType) throws ServiceException { 77 Object jsonObj = new JSONTokener(json).nextValue(); 78 JsonConfig jsonConfig = unserializableConfig.copy(); 79 80 //JSONArray和JSONObject不兼容,所以要先判断类型 81 if (jsonObj instanceof JSONArray) { 82 ArgumentChecker.notNull("classType", classType); 83 jsonConfig.setRootClass(classType); 84 JSONArray jsonArray = (JSONArray) jsonObj; 85 if (Array.class.isAssignableFrom(classType)) { 86 return JSONArray.toArray(jsonArray, jsonConfig); 87 } 88 return JSONArray.toCollection(jsonArray, jsonConfig); 89 } 90 91 JSONObject jsonObject = (JSONObject) jsonObj; 92 Class<?> clazz = classType; 93 if (classType != null) { 94 clazz = classType; 95 } 96 else { 97 String clazzName = jsonObject.getString("clazz"); 98 try { 99 clazz = Class.forName(clazzName); 100 } 101 catch (ClassNotFoundException e) { 102 throw new SystemException(MpfErrorCode.SYSTEM_ERROR, "实例化" + clazzName + "失败"); 103 } 104 } 105 jsonConfig.setRootClass(clazz); 106 return JSONObject.toBean(jsonObject, jsonConfig); 107 } 108 }
ObjectA和ObjectB实现getClazz接口,返回了自己的Class类型。
这时将TestJsonObj序列化后看到absProp增加了clazz属性:
{
"absProp": {
"clazz": "ObjectA",
"propA": "propA",
"propCommmon": "common"
},
"jsonProp": "aaaa"
}
反序列化时实例化clazz类型就可以了,见JsonConfig的配置。