Spring Boot自定义ObjectMapper反序列化对象验证失效问题排查
解决方案:保留Lombok注解同时触发JSR380反序列化校验
问题根源在于@Value + @Builder + @Jacksonized的组合下,Jackson通过Builder模式实例化对象,默认的JSR380校验只会在最终对象创建后执行,但此时Builder已经将null值传入不可变对象(@Value生成的类是不可变的),导致校验失效。以下是具体解决步骤:
1. 给模型类的Builder添加校验触发注解
在每个使用@Builder的模型类中,给自动生成的Builder内部类添加@Builder.Valid注解,让校验器在对象构建前就校验Builder的属性:
Address类示例
@Value @Builder(toBuilder = true) @Jacksonized public class Address { @NotNull private final String addrName; // 给Builder添加@Builder.Valid,触发构建前校验 @Builder.Valid public static class AddressBuilder {} }
Student类示例(注意嵌套对象的@Valid)
如果Student包含Address这类嵌套对象,必须给嵌套字段添加@Valid,确保嵌套对象的校验能被递归触发:
@Value @Builder(toBuilder = true) @Jacksonized public class Student { @NotNull private final String name; @Valid // 递归校验嵌套的Address对象 @NotNull private final Address address; @Builder.Valid public static class StudentBuilder {} }
2. 配置Jackson的ValidationModule为校验Builder模式
自定义ObjectMapper时,要明确设置ValidationModule的校验模式为VALIDATE_BUILDER,让校验器针对Builder实例而非最终对象执行校验:
// 初始化JSR380校验器 ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory(); Validator validator = validatorFactory.getValidator(); // 配置Jackson的ValidationModule ValidationModule validationModule = new ValidationModule(); validationModule.setValidator(validator); // 关键:设置校验时机为构建对象前校验Builder validationModule.setValidationMode(ValidationModule.ValidationMode.VALIDATE_BUILDER); // 注册模块到ObjectMapper ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(validationModule); // 其他Jackson配置(如序列化/反序列化规则)...
为什么@JsonProperty(required = true)无效?
@JsonProperty(required = true)仅作用于Jackson的反序列化规则:当JSON中完全缺失该字段时抛出异常,但如果JSON中明确传递了null值,这个注解不会触发校验逻辑,而@NotNull是JSR380的校验规则,必须通过校验器才能生效。
内容的提问来源于stack exchange,提问作者Trilochan Badhei
相关产品推荐
相关产品推荐

