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

Spring Boot自定义嵌套JSON校验:英寸/英尺字段和为0抛异常

Spring Boot 嵌套JSON公共对象全局校验实现

场景需求

项目接收嵌套结构JSON入参,JSON中多处复用两类公共对象:

  • InchFraction:包含inch、fraction两个数值字段
  • FeetInchFraction:包含feet、inch、fraction三个数值字段
    需要实现统一校验规则:
  • 任意位置的InchFraction对象如果inch + fraction = 0,直接抛出错误提示:invalid inch and fraction data
  • 任意位置的FeetInchFraction对象如果feet + inch + fraction = 0,直接抛出错误提示:invalid feet inch fraction data

参考入参示例

{
       "key1": 1,
       "key2": "xxxxxxxxxxxx",
       "key3": "xxxxxxxxx",
       "key4": "",
       "key5": "",
       "key6": {              
           "feet": 0,
           "inch": 1,
           "fraction": 0
       },
       "key7": "",
       "key8": {              
           "inch": 0,
           "fraction": 0
       },
       "key9": {              
           "inch": 1,
           "fraction": 1
       },
       "key10": {              
           "inch": 1,
           "fraction": 1
       },
       "key11": {              
           "inch": 1,
           "fraction": 1
       },
       "key12": {
           "key13": "",
           "key14": {                   
               "inch": 1,
               "fraction": 1
           },
           "key15": {                  
               "inch": 1,
               "fraction": 1
           }
       },
       "key16": {
           "key17": "",
           "key18": {                  
               "inch": 1,
               "fraction": 1
           },
           "key19": {                  
               "inch": 1,
               "fraction": 1
           }
       },
       "key20": "",
       "key21": "",
       "key22": "Welded",
       "key23": "Welded",
       "key24": {               
           "inch": 1,
           "fraction": 1
       },
       "key25": {               
           "inch": 1,
           "fraction": 1
       },
       "key26": {               
           "feet": 0,
           "inch": 1,
           "fraction": 0
       }
   
   }

现有模型定义

public class ShopstandardInputJSON {
    private float key1;
     private String key2;
     private String key3;
     private String key4;
     private String key5;
     private FeetInchFraction key6;
     private String key7;
     private InchFraction key8;
     private InchFraction key9;
     private InchFraction key10;
     private InchFraction key11;
     private Key12 key12;
     private Key16 key16;
     private String key20;
     private String key21;
     private String key22;
     private String key23;
     private InchFraction key24;
     private InchFraction key25;
     private FeetInchFraction key26;
}

public class InchFraction { 
    private int inch;
    private float fraction;
}

public class FeetInchFraction { 
    private int feet;
    private int inch;
    private float fraction;
}

实现步骤

不用手写递归遍历JSON的逻辑,直接用Spring Validation的类级别校验+嵌套校验能力,自动覆盖所有层级的公共对象:

1. 定义两类公共对象的自定义校验注解

首先给InchFraction写校验注解:

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = InchFractionValidator.class)
@Documented
public @interface ValidInchFraction {
    String message() default "invalid inch and fraction data";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

对应校验逻辑实现:

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

public class InchFractionValidator implements ConstraintValidator<ValidInchFraction, InchFraction> {
    @Override
    public boolean isValid(InchFraction value, ConstraintValidatorContext context) {
        if (value == null) return true;
        // 浮点数避免精度问题,用阈值判断
        return Math.abs(value.getInch() + value.getFraction()) > 0.0001f;
    }
}

再给FeetInchFraction写校验注解:

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FeetInchFractionValidator.class)
@Documented
public @interface ValidFeetInchFraction {
    String message() default "invalid feet inch fraction data";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

对应校验逻辑实现:

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

public class FeetInchFractionValidator implements ConstraintValidator<ValidFeetInchFraction, FeetInchFraction> {
    @Override
    public boolean isValid(FeetInchFraction value, ConstraintValidatorContext context) {
        if (value == null) return true;
        return Math.abs(value.getFeet() + value.getInch() + value.getFraction()) > 0.0001f;
    }
}

Spring Boot 2.x版本把上述代码里的jakarta.validation替换成javax.validation即可。

2. 修改模型类,添加校验触发标记

  • 给两个公共类加上对应的类级别校验注解
  • 所有自定义对象类型的字段(不管嵌套多少层)都加@Valid注解,告诉Spring Validation递归校验该字段内部的约束
    修改后的公共类:
// 用Lombok的话直接加@Data省掉getter/setter,手写也可以
@ValidInchFraction
public class InchFraction { 
    private int inch;
    private float fraction;
    // 补全getter/setter
    public int getInch() {return inch;}
    public void setInch(int inch) {this.inch = inch;}
    public float getFraction() {return fraction;}
    public void setFraction(float fraction) {this.fraction = fraction;}
}

@ValidFeetInchFraction
public class FeetInchFraction { 
    private int feet;
    private int inch;
    private float fraction;
    // 补全getter/setter
    public int getFeet() {return feet;}
    public void setFeet(int feet) {this.feet = feet;}
    public int getInch() {return inch;}
    public void setInch(int inch) {this.inch = inch;}
    public float getFraction() {return fraction;}
    public void setFraction(float fraction) {this.fraction = fraction;}
}

外层入口类修改示例:

import jakarta.validation.Valid;

public class ShopstandardInputJSON {
    private float key1;
    private String key2;
    private String key3;
    private String key4;
    private String key5;
    @Valid
    private FeetInchFraction key6;
    private String key7;
    @Valid
    private InchFraction key8;
    @Valid
    private InchFraction key9;
    @Valid
    private InchFraction key10;
    @Valid
    private InchFraction key11;
    @Valid
    private Key12 key12;
    @Valid
    private Key16 key16;
    private String key20;
    private String key21;
    private String key22;
    private String key23;
    @Valid
    private InchFraction key24;
    @Valid
    private InchFraction key25;
    @Valid
    private FeetInchFraction key26;
    // 补全所有getter/setter
}

内部嵌套类比如Key12、Key16同理,内部的InchFraction/FeetInchFraction字段都加上@Valid即可:

public class Key12 {
    private String key13;
    @Valid
    private InchFraction key14;
    @Valid
    private InchFraction key15;
    // 补全getter/setter
}

public class Key16 {
    private String key17;
    @Valid
    private InchFraction key18;
    @Valid
    private InchFraction key19;
    // 补全getter/setter
}

3. 接口层开启校验

在Controller接口的入参前加上@Valid注解,就会自动触发所有校验规则:

@PostMapping("/shop-standard/save")
public Object submit(@Valid @RequestBody ShopstandardInputJSON param) {
    // 正常业务逻辑处理
    return "success";
}

校验失败时会抛出MethodArgumentNotValidException,可以在全局异常处理器里捕获该异常,取出默认的错误信息返回给前端即可,不需要额外写递归遍历逻辑,不管两类公共对象嵌套在JSON的哪个位置,只要加了@Valid就会自动触发校验。


内容的提问来源于stack exchange,提问作者Naina Thange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:24:21