Gson序列化/反序列化抽象类问题:LinkedList<Request>反序列化失败
解决Gson反序列化LinkedList含抽象类子类的崩溃问题
我之前也遇到过几乎一模一样的问题——用Gson反序列化包含抽象类Parameter子类的LinkedList<Request>时总是崩溃,结合你的代码来看,问题核心有两个:
- Gson默认无法识别抽象类对应的具体子类,JSON里没有类型标识的话,它不知道该实例化
StringParameter还是PasswordParameter - Lombok的
@SuperBuilder和@Builder生成的构造逻辑,和Gson默认依赖的无参构造/字段赋值逻辑不兼容
下面是我亲测有效的解决步骤:
1. 给抽象类添加类型标识字段
首先要让JSON里带上能区分子类的标识,这样反序列化时能判断具体类型。修改你的Parameter抽象类,新增一个type字段:
@Data @SuperBuilder @NoArgsConstructor(access = AccessLevel.PROTECTED) // 给Gson提供实例化入口 public abstract class Parameter implements Serializable { private String key; private String type; // 类型标识,比如"string"或"password" public abstract Object getValue(); }
然后在子类里自动初始化type的值,确保序列化时这个字段会被写入JSON:
@Data @SuperBuilder @EqualsAndHashCode(callSuper = true) @NoArgsConstructor // 新增无参构造,兼容Gson public class StringParameter extends Parameter implements Serializable { private String value; @Override public Object getValue() { return value; } // 初始化类型标识 private void initType() { setType("string"); } // 利用Lombok的构造后钩子设置类型 @PostConstruct private void postConstruct() { initType(); } // 确保Builder创建实例时自动设置type public static class StringParameterBuilder extends Parameter.ParameterBuilder<StringParameter, StringParameterBuilder> { public StringParameterBuilder() { type("string"); } } }
PasswordParameter做类似修改,把type设为"password"即可。
2. 编写自定义Parameter反序列化器
接下来要写一个Gson的反序列化器,根据type字段的值,选择对应的子类实例化,同时兼容Lombok的Builder:
public class ParameterDeserializer implements JsonDeserializer<Parameter> { @Override public Parameter deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObj = json.getAsJsonObject(); String paramType = jsonObj.get("type").getAsString(); String key = jsonObj.get("key").getAsString(); String value = jsonObj.get("value").getAsString(); switch (paramType) { case "string": return StringParameter.builder() .key(key) .value(value) .type(paramType) .build(); case "password": return PasswordParameter.builder() .key(key) .value(value) .type(paramType) .build(); default: throw new JsonParseException("Unsupported parameter type: " + paramType); } } }
3. 注册反序列化器并构建Gson实例
最后把自定义的反序列化器注册到Gson里,然后就可以正常反序列化LinkedList<Request>了:
// 构建带自定义反序列化器的Gson实例 Gson gson = new GsonBuilder() .registerTypeAdapter(Parameter.class, new ParameterDeserializer()) .create(); // 反序列化LinkedList<Request>,注意用TypeToken指定泛型类型 String jsonStr = "你的JSON字符串"; LinkedList<Request> requestList = gson.fromJson(jsonStr, new TypeToken<LinkedList<Request>>() {}.getType());
额外注意事项
- 如果你的
Request类用了@Builder,要确保它也添加@NoArgsConstructor,否则Gson可能无法实例化Request对象 - 测试序列化后的JSON,确认每个
Parameter都带有type字段,这是反序列化的关键 - 如果还是有问题,可以尝试关闭Gson的
serializeNulls配置,避免空值字段干扰反序列化逻辑
内容的提问来源于stack exchange,提问作者Tatiana B
相关产品推荐
相关产品推荐

