gson反序列化抽象类最佳实践

基于上篇文章《gson反序列化抽象类的尝试》:

https://blog.csdn.net/starry_eve/article/details/108285320

上篇说道反序列化抽象类不稳定,因为抽象类必须在type的后面。

现在作者发现了稳定反序列化抽象类的方法,即抽象类和type要以key-value的形式存在于map中,key必然在json串中value的前面,所以解析value时必然知道是什么类型。

核心方法是:

Gson#getDelegateAdapter()
GsonBuilder#registerTypeAdapterFactory()

因为要反序列化对象用到类:

ReflectiveTypeAdapterFactory#Adapter

然而这个类的构造相当复杂,因此

registerTypeAdapter()

方法束手无策,我们只能自定义TypeAdapter的创建过程。

因为map中key与value相邻,所以在key反序列化时保存下类型值,然后TypeAdapter创建时使用保存下的类型值,把为此抽象类创建TypeAdapter流程改为创建其派生类的TypeAdapter。

废话不说,抽象类反序列化工具:

/**
 * Gson抽象类反序列化工具。
 * 注意:只适用于Map中,类型值作为key,抽象类作为value。
 */
public class AbstractClassDecoder {

    private static final String TAG = AbstractClassDecoder.class.getSimpleName();
    private Map<Integer, Class<?>> classReflectMap;
    private Class<?> absClazz;
    private int msgType = 0;
    private boolean lock = false;

    /**
     * 使GsonBuilder对象可反序列化抽象类
     * @param absClazz 抽象类
     * @param classReflectMap 消息类型和类的映射表
     * @return GsonBuilder对象
     */
    public static GsonBuilder enableAbstractClassDecode(Class<?> absClazz, Map<Integer, Class<?>> classReflectMap){
        GsonBuilder result = new GsonBuilder();
        new AbstractClassDecoder(result, absClazz, classReflectMap);
        return result;
    }

    private AbstractClassDecoder(){
        // disabled
    }

    private AbstractClassDecoder(GsonBuilder gsonBuilder, Class<?> absClazz, Map<Integer, Class<?>> classReflectMap) {
        if (gsonBuilder == null || classReflectMap == null){
            throw new IllegalArgumentException();
        }

        this.absClazz = absClazz;
        this.classReflectMap = classReflectMap;

        TypeAdapterFactory INTEGER_FACTORY = TypeAdapters.newFactory(int.class,
                Integer.class,
                new MsgTypeIntAdapter());

        gsonBuilder.registerTypeAdapterFactory(new AbstractClassDecoder.MsgBodyAdapterFactory())
                .registerTypeAdapterFactory(INTEGER_FACTORY);
    }

    private class MsgTypeIntAdapter extends TypeAdapter<Number> {
        @Override
        public Number read(JsonReader in) throws IOException {
            if (in.peek() == JsonToken.NULL) {
                in.nextNull();
                return null;
            }
            try {
                int intVal = in.nextInt();
                if (!lock){
                    msgType = intVal;
                }
                return intVal;
            } catch (NumberFormatException e) {
                throw new JsonSyntaxException(e);
            }
        }
        @Override
        public void write(JsonWriter out, Number value) throws IOException {
            out.value(value);
        }
    };

    private class MsgBodyAdapterFactory implements TypeAdapterFactory {

        @Override
        public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
            return new TypeAdapter<T>() {
                @Override
                public void write(JsonWriter out, T value) throws IOException {
                    getDelegate(MsgBodyAdapterFactory.this, gson, type)
                            .write(out,value);
                }

                @Override
                public T read(JsonReader in) throws IOException {
                    // 尝试获取抽象类类型
                    TypeToken<T> absType = null;
                    String typeName = type.getRawType().getName();
                    if (typeName.equals(absClazz.getName())){
                        Class<?> clazz = classReflectMap.get(msgType);
                        if (clazz != null){
                            absType = (TypeToken<T>) TypeToken.get(clazz);
                        }
                    }

                    if (absType != null){
                        lock = true;
                    }

                    TypeToken<T> finalType = absType != null ? absType : type;
                    T result = getDelegate(MsgBodyAdapterFactory.this, gson, finalType)
                            .read(in);
                    Log.d(TAG, "反序列化对象: " + type + " -> " + finalType);

                    if (absType != null){
                        lock = false;
                    }

                    return result;
                }
            };
        }
    }

    /**
     * 获取当前gson对象的代理TypeAdapter
     * @param typeAdapterFactory 除了这个工厂,其他工厂都会被遍历最终生成TypeAdapter。
     *                           因为这个工厂也被加到gson对象中了,所以如果不排除会死循环。
     * @param gson gson对象
     * @param type 类型令牌
     * @param <T> 类型泛型
     * @return 类型适配器
     */
    private static <T> TypeAdapter<T> getDelegate(TypeAdapterFactory typeAdapterFactory, Gson gson, TypeToken<T> type){
        return gson.getDelegateAdapter(typeAdapterFactory, type);
    }
}

下面给出测试代码使用的类:

public interface AbsMsg {
}

public class Resp {
    private int magic = 10;
    private Map<Integer, List<AbsMsg>> map = new HashMap<>();

    public Resp() {
        List<AbsMsg> msgList1 = new ArrayList<>();
        msgList1.add(new Msg());
        map.put(200, msgList1);

        List<AbsMsg> msgList2 = new ArrayList<>();
        msgList2.add(new Msg2());
        map.put(201, msgList2);
    }

    public static class Msg implements AbsMsg{
        private List<AtBean> a1 = new ArrayList<>();
        private String b1 = "我是消息1";
        private int z1 = 9999;

        public Msg() {
            a1.add(new AtBean());
            a1.add(new AtBean());
        }
    }

    public static class AtBean{
        private String id = "atUid";
    }

    public static class Msg2 implements AbsMsg{
        private String b2 = "我是消息2";
        private String c2 = "c2";
        private int d2 = 1234567;
    }
}

然后是测试代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Map<Integer, Class<?>> reflectMap = new HashMap<>();
        reflectMap.put(200, Resp.Msg.class);
        reflectMap.put(201, Resp.Msg2.class);

        String json = new Gson().toJson(new Resp());

        Gson gson = AbstractClassDecoder
                .enableAbstractClassDecode(AbsMsg.class, reflectMap)
                .create();
        Resp decode = gson.fromJson(json, Resp.class);
        Log.i("AbstractClassDecoder", gson.toJson(decode));
    }
}

最后是测试结果:

2020-11-06 19:02:45.951 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: java.lang.String -> java.lang.String
2020-11-06 19:02:45.951 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: com.nykj.testgson.Resp$AtBean -> com.nykj.testgson.Resp$AtBean
2020-11-06 19:02:45.952 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: java.lang.String -> java.lang.String
2020-11-06 19:02:45.952 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: com.nykj.testgson.Resp$AtBean -> com.nykj.testgson.Resp$AtBean
2020-11-06 19:02:45.952 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: java.util.List<com.nykj.testgson.Resp$AtBean> -> java.util.List<com.nykj.testgson.Resp$AtBean>
2020-11-06 19:02:45.952 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: java.lang.String -> java.lang.String
2020-11-06 19:02:45.953 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: com.nykj.testgson.AbsMsg -> com.nykj.testgson.Resp$Msg
2020-11-06 19:02:45.953 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: java.util.List<com.nykj.testgson.AbsMsg> -> java.util.List<com.nykj.testgson.AbsMsg>
2020-11-06 19:02:45.956 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: java.lang.String -> java.lang.String
2020-11-06 19:02:45.956 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: java.lang.String -> java.lang.String
2020-11-06 19:02:45.956 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: com.nykj.testgson.AbsMsg -> com.nykj.testgson.Resp$Msg2
2020-11-06 19:02:45.956 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: java.util.List<com.nykj.testgson.AbsMsg> -> java.util.List<com.nykj.testgson.AbsMsg>
2020-11-06 19:02:45.957 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: java.util.Map<java.lang.Integer, java.util.List<com.nykj.testgson.AbsMsg>> -> java.util.Map<java.lang.Integer, java.util.List<com.nykj.testgson.AbsMsg>>
2020-11-06 19:02:45.957 16281-16281/com.nykj.testgson D/AbstractClassDecoder: 反序列化对象: com.nykj.testgson.Resp -> com.nykj.testgson.Resp
2020-11-06 19:02:45.972 16281-16281/com.nykj.testgson I/AbstractClassDecoder: {"magic":10,"map":{"200":[{"a1":[{"id":"atUid"},{"id":"atUid"}],"b1":"我是消息1","z1":9999}],"201":[{"b2":"我是消息2","c2":"c2","d2":1234567}]}}

从此之后,成熟的实践(奇怪的知识)+1。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值