Gson导入导出Shape继承类列表时报无参构造调用失败如何解决
问题原因
你遇到的两个问题本质都是Gson默认不支持多态类型的序列化/反序列化导致的:
- 最初的
Failed to invoke public Shape() with no args报错:Gson反序列化时需要先实例化目标类型的对象,而Shape是抽象类,无法直接被实例化,同时你也没有为Shape定义无参构造方法,直接触发实例化失败异常。 - 移除
abstract修饰符后丢失子类属性:Gson默认序列化时不会保存对象的实际运行时类型信息,只会按照你声明的List<Shape>静态类型进行序列化,所有子类实例都会被向上转型为Shape结构输出,反序列化时也只会生成Shape类型的对象,自然不会带有子类的a、b等特有属性。
解决方案
使用Gson官方提供的RuntimeTypeAdapterFactory多态类型适配器解决,操作步骤如下:
1. 引入依赖
RuntimeTypeAdapterFactory属于Gson扩展包,需要额外引入依赖(以Maven为例):
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson-extras</artifactId> <version>和你项目中gson核心包的版本保持一致</version> </dependency>
2. 补充无参构造方法
为Shape抽象类和所有子类添加protected级别的无参构造,供Gson实例化对象使用:
// Shape类补充 protected Shape() {} // Rectangle类补充 protected Rectangle() {} // Circle、Square同理补充
3. 注册多态类型适配器
在初始化Gson时注册RuntimeTypeAdapterFactory,指定基类、类型标识字段、以及所有子类对应的标识:
// 统一创建Gson实例的配置,序列化和反序列化都要用同一个配置的Gson对象 RuntimeTypeAdapterFactory<Shape> shapeAdapterFactory = RuntimeTypeAdapterFactory .of(Shape.class, "shapeType") // 第二个参数为JSON中存储类型标识的字段名,序列化时自动写入 .registerSubtype(Rectangle.class, "RECTANGLE") .registerSubtype(Circle.class, "CIRCLE") .registerSubtype(Square.class, "SQUARE"); Gson gson = new GsonBuilder() .registerTypeAdapterFactory(shapeAdapterFactory) .create();
4. 调整原有导入导出方法
把原来方法中默认创建的Gson实例替换为上面配置好的实例即可:
public static List<Shape> importShapeListFromJsonWithGson(String path) throws IOException { Type listType = new TypeToken<List<Shape>>() {}.getType(); // 用上面配置好的gson实例,不要用默认的new GsonBuilder().create() Reader reader = new FileReader(path); List<Shape> result = gson.fromJson(reader, listType); reader.close(); return result; } public static void exportShapeListToJsonWithGson(List<Shape> list, String path) throws IOException { Writer writer = new FileWriter(path); // 用上面配置好的gson实例 gson.toJson(list, writer); writer.close(); }
额外说明
- 序列化生成的JSON会自动新增
shapeType字段,值为你注册的子类标识,反序列化时Gson会根据这个字段自动匹配对应的子类实例化,完整保留子类所有属性。 - 如果不希望
shapeType字段保留在反序列化后的对象属性中,可以将适配器初始化代码改为RuntimeTypeAdapterFactory.of(Shape.class, "shapeType", true),第三个参数设为true即可自动忽略该字段。
内容的提问来源于stack exchange,提问作者Lulex97
相关产品推荐
相关产品推荐

