Gson反序列化仅生成父类实例问题求助
解决Gson反序列化父类字段仅生成父类实例的问题
这个问题我之前也碰到过!Gson默认是按照字段的声明类型来反序列化的——哪怕你初始化时给的是Fool2子类实例,序列化后再反序列化,Gson只会认Fool这个声明类型,自然就只创建Fool实例了。不过有两种靠谱的解决办法:
方法一:使用官方的RuntimeTypeAdapterFactory(推荐)
Gson的扩展库gson-extras提供了RuntimeTypeAdapterFactory,专门用来处理多态类型的序列化/反序列化,这是最简洁可靠的方案。
步骤1:引入依赖
如果用Maven,在pom.xml里添加:
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson-extras</artifactId> <version>2.10.1</version> <!-- 建议使用最新稳定版 --> </dependency>
步骤2:编写代码实现
注意:你的自定义类名不要用Object,会和java.lang.Object冲突,我改成MyObject了:
// 父类 public class Fool {} // 子类 public class Fool2 extends Fool {} // 包含Fool字段的类 public class MyObject { private Fool fool = new Fool2(); } // 测试类 public class GsonPolymorphicDemo { public static void main(String[] args) { // 创建类型适配器工厂,指定父类Fool,用"type"字段区分子类 RuntimeTypeAdapterFactory<Fool> typeFactory = RuntimeTypeAdapterFactory.of(Fool.class, "type") .registerSubtype(Fool2.class, "fool2"); // 注册子类并指定标识值 // 构建带有该工厂的Gson实例 Gson gson = new GsonBuilder() .registerTypeAdapterFactory(typeFactory) .create(); // 序列化 MyObject original = new MyObject(); String json = gson.toJson(original); System.out.println(json); // 输出会包含"type":"fool2"字段 // 反序列化 MyObject deserialized = gson.fromJson(json, MyObject.class); System.out.println(deserialized.fool.getClass()); // 输出class Fool2,符合预期 } }
这个工厂会在序列化时自动添加一个标识字段(比如这里的"type"),反序列化时根据这个字段判断应该实例化哪个子类。
方法二:手动存储类路径
如果你不想引入额外依赖,可以手动在序列化时存储子类的全限定类名,反序列化时根据类名创建实例:
import com.google.gson.Gson; import com.google.gson.JsonObject; public class ManualTypeHandlingDemo { // 自定义类(避免和系统Object冲突) public static class MyObject { private Fool fool = new Fool2(); // 用于存储子类的类路径 private String foolClassType; // 序列化前先设置类路径 public void prepareForSerialize() { this.foolClassType = fool.getClass().getName(); } } public static void main(String[] args) throws Exception { Gson gson = new Gson(); MyObject original = new MyObject(); original.prepareForSerialize(); // 序列化 String json = gson.toJson(original); // 反序列化第一步:解析JSON对象,获取类路径 JsonObject jsonObj = gson.fromJson(json, JsonObject.class); String classPath = jsonObj.get("foolClassType").getAsString(); Class<? extends Fool> subclass = (Class<? extends Fool>) Class.forName(classPath); // 反序列化fool字段到具体子类 Fool fool = gson.fromJson(jsonObj.get("fool"), subclass); MyObject deserialized = new MyObject(); deserialized.fool = fool; System.out.println(deserialized.fool.getClass()); // 输出class Fool2 } }
这种方法需要手动处理类路径的存储和解析,适合不想引入额外依赖的场景,但代码相对繁琐一些。
内容的提问来源于stack exchange,提问作者Eytera
相关产品推荐
相关产品推荐

