zoukankan      html  css  js  c++  java
  • 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 }
    AbstracObj
     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 }
    ObjectA
     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 }
    ObjectB
     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

    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 }
    ObjectA
     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 }
    ObjectB
      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 }
    TestJsonObj

    ObjectA和ObjectB实现getClazz接口,返回了自己的Class类型。

    这时将TestJsonObj序列化后看到absProp增加了clazz属性:

    {
        "absProp": {
            "clazz": "ObjectA",
            "propA": "propA",
            "propCommmon": "common"
        },
        "jsonProp": "aaaa"
    }
    Json串

    反序列化时实例化clazz类型就可以了,见JsonConfig的配置。

  • 相关阅读:
    图片的下方与父元素有间隙兼容性解决方案
    vscode 实用插件
    给网页title前面上图标
    网站换肤
    基于面向对象编程的设计模式
    点击获取验证码进行60秒倒计时
    JVM--内存模型与线程
    JVM学习--jvm监控和故障处理工具
    JVM--GC学习
    JVM--Java类加载机制
  • 原文地址:https://www.cnblogs.com/BensonHe/p/4614478.html
Copyright © 2011-2022 走看看