Gson泛型类型适配器基类反序列化:基类与子类适配异常
解决Gson继承类反序列化:基类Kit解析失败的问题
这个问题我之前也碰到过,核心是Gson默认对继承关系的反序列化支持不够灵活,加上你注册的类型适配器可能只适配了子类ExtendedKit,导致解析基类Kit的JSON时,因为找不到子类特有的extraProperty字段而报错。下面给你两个实用的解决方案,不用写大量类型适配器就能搞定:
方案1:使用RuntimeTypeAdapterFactory(官方推荐)
Gson有个专门处理多态反序列化的扩展类RuntimeTypeAdapterFactory,它通过在JSON里添加一个类型标识字段,来区分要解析成基类还是子类,扩展性很强,适合有多个子类的场景。
步骤:
- 先创建类型适配器工厂,指定基类、类型标识字段名,然后注册所有子类:
// 需引入com.google.gson:gson-extras依赖(如果项目还没添加) RuntimeTypeAdapterFactory<Kit> kitTypeFactory = RuntimeTypeAdapterFactory.of(Kit.class, "type") .registerSubtype(Kit.class, "kit") // 基类对应的类型标识值 .registerSubtype(ExtendedKit.class, "extendedKit"); // 子类对应的类型标识值
- 将这个工厂注册到
GsonBuilder:
Gson gson = new GsonBuilder() .registerTypeAdapterFactory(kitTypeFactory) .create();
- 对应的JSON格式需要带上类型标识:
- 基类
Kit的JSON:
{"type":"kit", "baseProperty":"value"}
- 子类
ExtendedKit的JSON:
{"type":"extendedKit", "baseProperty":"value", "extraProperty":"extraValue"}
这样Gson会根据type字段自动选择对应的类进行反序列化,基类和子类都能正常解析。
方案2:自定义通用类型适配器(无需类型标识字段)
如果不想在JSON里加额外的类型标识字段,可以写一个针对基类Kit的自定义适配器,通过判断JSON中是否存在子类特有的字段,来决定实例化哪个类。
实现代码:
public class KitTypeAdapter extends TypeAdapter<Kit> { // 用默认Gson处理具体的序列化/反序列化逻辑 private final Gson defaultGson = new Gson(); @Override public void write(JsonWriter out, Kit value) throws IOException { // 序列化时判断对象实际类型,对应写入JSON if (value instanceof ExtendedKit) { defaultGson.toJson(value, ExtendedKit.class, out); } else { defaultGson.toJson(value, Kit.class, out); } } @Override public Kit read(JsonReader in) throws IOException { // 先把JSON读成JsonElement,方便后续判断字段 JsonElement jsonElement = defaultGson.fromJson(in, JsonElement.class); JsonObject jsonObject = jsonElement.getAsJsonObject(); // 判断是否存在子类ExtendedKit特有的字段extraProperty if (jsonObject.has("extraProperty")) { return defaultGson.fromJson(jsonElement, ExtendedKit.class); } else { return defaultGson.fromJson(jsonElement, Kit.class); } } }
注册适配器:
Gson gson = new GsonBuilder() .registerTypeAdapter(Kit.class, new KitTypeAdapter()) .create();
这样处理后,不管是带extraProperty的子类JSON,还是不带的基类JSON,都能被正确解析,不会因为找不到字段而报错。
注意事项
- 如果之前你只注册了
ExtendedKit的类型适配器,Gson在解析Kit类型时可能会因为类型擦除,错误地尝试用子类的适配器解析,导致报错。所以一定要针对基类来注册适配器,覆盖所有子类的情况。 - 方案1的
RuntimeTypeAdapterFactory属于Gson的扩展库,需要确保你的项目中引入了gson-extras依赖(Maven/Gradle均可配置)。
内容的提问来源于stack exchange,提问作者driima
相关产品推荐
相关产品推荐

