FastJson下抽象类的反序列化解决思路

背景

AResult A结果
BResult B结果
AbstractResult 结果基类


问题现象

在存入mongo时结果将会以List<AbstractResult> 序列化存入mongo,但是在取出结果时出现了问题。

通过mongo取出数据后,希望还原成为List<AbstractResult> ,于是通过反序列化来还原格式,此时出现问题,因为AbstractResult是抽象类,在进行反序列化时,无法反序列化成为对应的类。于是反序列化出来的List内元素全是null

解决思路一

通过网上查询有关FastJson抽象类反序列化的解决办法,只找到了一篇相关:https://www.cnblogs.com/549294286/p/8215109.html

本文的解决思路是编写ParserConfig类,类中复写getDeserializer(Type type)方法,并在JSON.parseObject时作为参数传入,该方法是用来根据类名来返回具体的反序列化方法的,通过复写该方法,在遇到Type为AbstractResult.class时,就可以返回指定的子类的反序列化方法,如

ParserConfig parserConfig = new ParserConfig() {
     @Override
     public ObjectDeserializer getDeserializer(Type type) {
            if (type == ActionConfig.class) {
                return super.getDeserializer(LimitActionConfig.class);
             }
             return super.getDeserializer(type);
     }
};

BResult方法或者AResult方法。尝试该解决思路,发现在整个list都是同一种子类时可以实现正常的反序列化,将整个List反序列化为AResult或者BResult。

解决思路二

上面的解决方法虽然能够成功,但是并不能解决实际遇到的问题,因为实际需要进行反序列化的List中的类型不是统一的,而是AResult和BResult同时存在的,所以必须有更加精确的反序列化方法。

网上没有类似问题的解决思路,于是只能翻阅源码查找解决思路。在查看了大量源码之后,找到了解决方案。

本解决方案借鉴了思路一的方法,在遇到Type为AbstractResult.class时,返回我自己编写的自定义的反序列化方法。代码如下

private static final ParserConfig parserConfig = new ParserConfig() {
    @Override
    public ObjectDeserializer getDeserializer(Type type) {
        if (type == AbstractResult.class) {
            return new AbstractResultDeserializer();
        }
        return super.getDeserializer(type);
    }
};


其中AbstractResultDeserializer的源码如下

public class AbstractResultDeserializer implements ObjectDeserializer {
    public static final String CHARACTERISTIC = "characteristic";
    @Override
    public <T> T deserialze(DefaultJSONParser parser, Type type, Object object) {
        String text = (String) parser.input; //需要反序列化的文本
        int begin = ((JSONScanner) parser.lexer).pos()+1;//当前反序列化进行到的位置
        text = text.substring(begin,findEndPoint(text,begin));
        if (text.contains(CHARACTERISTIC)){
            AbstractResult AResult = 
               parser.getConfig().getDeserializer(AResult.class).deserialze(parser,type, 
               object);
            return (T) AResult;
         }else {
            AbstractResult BResult =
               parser.getConfig().getDeserializer(BResult.class).deserialze(parser, 
               type, object);
            return (T) BResult;
         }
    }

   @Override
   public int getFastMatchToken() {
          return 0;
   }

   public static Integer findEndPoint(String text , int begin){
        int stack =0;
        int t;
        for (t = begin; t < text.length(); t++) {
            char ch = text.charAt(t);
            if (ch  == '{'){
                stack++;
            }
            if (ch == '}'){
                if (stack == 0){
                    break;
                }else {
                    stack--;
                }
            }
        }
        return t;
   }
}


自定义反序列化的具体反序列过程就是通过重写deserialze()方法实现,下面介绍一下方法内的变量和函数

CHARACTERISTIC AResult类中特有的变量名称

text  反序列化的总文本

begin List反序列化进行到的位置

findEndPoint()该函数能找到当前反序列化类在文本中的结束位置

该自定义反序列化主要逻辑为

1.从整体List需要反序列化的文本中分割出当前类的文本

2.判断文本中是否存在AResult类中特有的变量名称

3.若存在则调用AResult的反序列方法

4.若不存在则调用BResult的反序列方法

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值