基于上篇文章《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。