如何使用Jackson反序列化带有Lombok @SuperBuilder注解的类
报错根因
你使用的@Value是Lombok的不可变类注解,会默认仅生成全参数构造方法,无默认无参构造,而Jackson 2.9.7默认需要无参构造,或者标记了@JsonCreator的构造方法才能完成反序列化,加上父类继承、@SuperBuilder默认不会生成Jackson可识别的构造注解,所以触发找不到构造器的报错。
方案1:可修改UpperClass、BaseClass源码的场景
可选实现1:添加私有强制无参构造
给两个类都添加@NoArgsConstructor注解,设置force=true强制给final字段赋默认值,Jackson会通过反射后续覆盖字段值,无需修改其他逻辑:
// BaseClass修改 @Value @NonFinal @SuperBuilder @AllArgsConstructor @NoArgsConstructor(force = true, access = AccessLevel.PRIVATE) public class BaseClass { protected String status; } // UpperClass修改 @Value @NonFinal @SuperBuilder @EqualsAndHashCode(callSuper=true) @NoArgsConstructor(force = true, access = AccessLevel.PRIVATE) public class UpperClass extends BaseClass { String message; }
可选实现2:给全参构造添加反序列化标识
给两个类的全参构造添加@JsonCreator注解,同时给字段加@JsonProperty匹配JSON字段名:
// BaseClass修改 @Value @NonFinal @SuperBuilder @AllArgsConstructor(onConstructor = @__(@JsonCreator)) public class BaseClass { @JsonProperty("status") protected String status; } // UpperClass修改 @Value @NonFinal @SuperBuilder @EqualsAndHashCode(callSuper=true) @AllArgsConstructor(onConstructor = @__(@JsonCreator)) public class UpperClass extends BaseClass { @JsonProperty("message") String message; }
方案2:类来自外部库、无法修改源码的场景
自定义Jackson反序列化器,手动构造对象,再注册到Spring的全局ObjectMapper中即可:
- 编写自定义反序列化器
public class UpperClassDeserializer extends StdDeserializer<UpperClass> { public UpperClassDeserializer() { super(UpperClass.class); } @Override public UpperClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); String status = node.has("status") ? node.get("status").asText() : null; String message = node.has("message") ? node.get("message").asText() : null; // 调用Lombok生成的builder构造实例 return UpperClass.builder().status(status).message(message).build(); } }
- 注册反序列化器到Spring Boot全局配置
@Configuration public class JacksonCustomConfig { @Bean public ObjectMapper registerCustomDeserializer() { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(UpperClass.class, new UpperClassDeserializer()); mapper.registerModule(module); return mapper; } }
方案3:无注解轻量实现
启用编译参数-parameters保留构造参数名,同时给Jackson注册参数名识别模块,无需给每个字段加@JsonProperty:
- 给项目编译插件添加参数,以Maven为例:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin>
- 注册参数名解析模块
@Bean public Module parameterNamesModule() { return new ParameterNamesModule(); }
- 给两个类的全参构造添加
@JsonCreator注解即可完成反序列化。
内容的提问来源于stack exchange,提问作者Yuri Molodyko
相关产品推荐
相关产品推荐

