Spring Boot中@JsonUnwrapped+泛型继承反序列化空值校验失败问题
问题分析与解决方案
问题核心
在Spring Boot 3.4.0(Jackson 2.18.1)场景下,结合@JsonUnwrapped扁平化请求体、继承与泛型特性时,出现了**Bar1的@JsonCreator能正确解析参数,但getFoo()返回null,触发Foo1的foo1字段@NotBlank校验报错**的问题。
原因在于:@JsonUnwrapped会指示Jackson在反序列化时尝试解析父类的foo字段,但请求JSON中仅包含展开后的foo1、foo2字段,没有顶层foo字段,导致Jackson将foo字段覆盖为null,抵消了你在构造器中通过super(bar1, new Foo1(foo1, foo2))初始化的值。
解决方案(无需自定义反序列化器)
只需调整@JsonUnwrapped的配置,让它仅在序列化阶段生效,反序列化阶段忽略该字段,避免Jackson覆盖手动初始化的foo实例。
方案1:修改@JsonUnwrapped的反序列化开关
修改AbstractBar类中的foo字段注解:
public abstract class AbstractBar<F extends AbstractFoo> { @Pattern(regexp = "\\d{2}") protected final String bar1; @Valid @JsonUnwrapped(deserialization = false) // 仅序列化时展开,反序列化不处理该字段 protected final F foo; // 构造器、getter方法不变 }
方案2:添加@JsonProperty(access = READ_ONLY)
通过标记字段为只读,让Jackson仅在序列化时处理它:
public abstract class AbstractBar<F extends AbstractFoo> { @Pattern(regexp = "\\d{2}") protected final String bar1; @Valid @JsonUnwrapped @JsonProperty(access = JsonProperty.Access.READ_ONLY) // 反序列化时忽略该字段 protected final F foo; // 构造器、getter方法不变 }
验证效果
修改后重新发送请求,Jackson会通过@JsonCreator构造器正确创建Bar1实例,父类的foo字段将保持构造器中初始化的Foo1对象,getFoo()不再返回null,foo1的@NotBlank校验也能正常通过。
内容的提问来源于stack exchange,提问作者Nathan S
相关产品推荐
相关产品推荐

