You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:37:09