Spring Boot中如何用javax.validation验证嵌套JSON请求字段
实现ItemCode的规则验证方案
要满足你描述的ItemCode校验规则(codeType只能是1/2/3,codeValue长度和codeType匹配),需要通过自定义JSR-380校验注解来实现——这是跨字段的关联校验,原生注解无法直接满足需求。以下是具体实现步骤:
1. 自定义校验注解
创建一个自定义注解ValidItemCode,用来标记需要校验的ItemCode对象:
import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*; @Documented @Constraint(validatedBy = ItemCodeValidator.class) @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ValidItemCode { String message() default "ItemCode不符合规则:codeType只能是1/2/3,且codeValue长度需匹配对应codeType"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
2. 实现校验器逻辑
编写ItemCodeValidator类,实现ConstraintValidator接口,具体处理校验逻辑:
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import java.util.Map; public class ItemCodeValidator implements ConstraintValidator<ValidItemCode, ItemCode> { // 定义codeType对应的codeValue长度映射 private static final Map<Integer, Integer> CODE_LENGTH_MAP = Map.of( 1, 3, 2, 4, 3, 5 ); @Override public boolean isValid(ItemCode itemCode, ConstraintValidatorContext context) { // 先判断codeType是否在允许范围内 if (!CODE_LENGTH_MAP.containsKey(itemCode.getCodeType())) { return false; } // 再判断codeValue的长度是否匹配对应codeType要求 Integer requiredLength = CODE_LENGTH_MAP.get(itemCode.getCodeType()); return itemCode.getCodeValue() != null && itemCode.getCodeValue().length() == requiredLength; } }
3. 在ItemCode类上应用自定义注解
修改ItemCode类,添加自定义的@ValidItemCode注解,同时保留原有的@NotNull注解:
import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotNull; @ValidItemCode // 添加自定义校验注解 @AllArgsConstructor @NoArgsConstructor @Getter @Setter public class ItemCode { @NotNull @Schema(description="codeType can be 1, 2, or 3" , requiredMode = Schema.RequiredMode.REQUIRED) private int codeType; @NotNull @Schema(description="Unique itemCode identifier. Can start with 0. If codeType=1, 3-digits long, if codeType=2, 4-digits long, if codeType=3, 5-digits long.", requiredMode = Schema.RequiredMode.REQUIRED) private String codeValue; // for example 021, 5455, 05324 }
4. 确保Controller层触发校验
在接收请求的Controller方法中,对ItemRequest参数添加@Valid注解,Spring会自动触发嵌套对象的校验:
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController public class ItemController { @PostMapping("/items") public String createItem(@Valid @RequestBody ItemRequest itemRequest) { // 处理业务逻辑 return "Item created successfully"; } }
补充优化(可选)
如果需要更精准的错误提示(比如分别提示codeType非法还是codeValue长度不匹配),可以修改校验器的isValid方法,自定义错误信息:
@Override public boolean isValid(ItemCode itemCode, ConstraintValidatorContext context) { context.disableDefaultConstraintViolation(); // 关闭默认提示 if (!CODE_LENGTH_MAP.containsKey(itemCode.getCodeType())) { context.buildConstraintViolationWithTemplate("codeType只能是1、2或3") .addPropertyNode("codeType") .addConstraintViolation(); return false; } Integer requiredLength = CODE_LENGTH_MAP.get(itemCode.getCodeType()); if (itemCode.getCodeValue() == null || itemCode.getCodeValue().length() != requiredLength) { context.buildConstraintViolationWithTemplate(String.format("codeType为%d时,codeValue必须是%d位长度", itemCode.getCodeType(), requiredLength)) .addPropertyNode("codeValue") .addConstraintViolation(); return false; } return true; }
注:Spring Boot 2.7.6默认集成了Hibernate Validator(JSR-380的实现),无需额外引入依赖。
内容的提问来源于stack exchange,提问作者cd491415
相关产品推荐
相关产品推荐

