如何通过Swagger注解配置自定义数字错误码?
问题描述
我在OpenAPI契约中定义了如下用于表示佣金金额的Schema:
"properties": { "Amount": { "type": "number", "description": "The amount of tnx", "pattern" : "^-?[0-9]*(\\.([0-9]{1,2}))?$", "format": "big-decimal", "minimum": 0.01, "maximum": 49999.99, "exclusiveMinimum": false, "exclusiveMaximum": false, "example" : "9999.99" } }
生成的Java代码如下:
@NotNull @Valid @DecimalMin("0.01") @DecimalMax("49999.99") @Schema(name = "amount", example = "9999.99", description = "The amount of tnx", required = true) public BigDecimal getAmount() { return amount; }
当输入金额超过49999.99或低于0.01时,Postman返回的验证信息如下:
{ "errors": [ { "code": "DecimalMax", "message": "must be less than or equal to 49999.99", "field": "Amount" } ] } { "errors": [ { "code": "DecimalMin", "message": "must be greater than or equal to 0.01", "field": "Amount" } ] }
但我希望将其中的错误码替换为自定义数字,比如:
{ "errors": [ { "code": "100", "message": "must be less than or equal to 49999.99", "field": "Amount" } ] } { "errors": [ { "code": "101", "message": "must be greater than or equal to 0.01", "field": "Amount" } ] }
请问是否可以通过Swagger注解实现这一需求?
解答
不能直接通过Swagger(OpenAPI)注解实现自定义错误码的需求,原因如下:
- Swagger的
@Schema等注解核心作用是生成API文档,不负责后端验证逻辑的执行和错误码映射。 - 当前使用的
@DecimalMin、@DecimalMax属于JSR-380(Java Bean Validation)规范的注解,验证逻辑由Spring Validation这类框架执行,默认返回的错误码是约束注解的名称(如DecimalMax)。
要实现自定义数字错误码,需要通过全局异常处理器拦截验证异常,将默认错误码替换为自定义值,具体步骤和示例代码如下:
实现步骤
- 创建全局异常处理器类,捕获请求体/参数验证时抛出的
MethodArgumentNotValidException、ConstraintViolationException。 - 定义约束类型与自定义错误码的映射关系。
- 遍历异常中的验证错误,替换错误码并构造符合要求的响应格式返回。
示例代码
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import jakarta.validation.ConstraintViolation; import jakarta.validation.ConstraintViolationException; import java.util.ArrayList; import java.util.List; import java.util.Map; @RestControllerAdvice public class GlobalValidationExceptionHandler { // 约束类型到自定义错误码的映射 private static final Map<String, String> CONSTRAINT_ERROR_CODE_MAP = Map.of( "DecimalMax", "100", "DecimalMin", "101" ); // 处理请求体验证异常 @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ErrorResponse> handleRequestBodyValidation(MethodArgumentNotValidException ex) { List<ErrorDetail> errors = new ArrayList<>(); for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) { String customCode = CONSTRAINT_ERROR_CODE_MAP.getOrDefault(fieldError.getCode(), fieldError.getCode()); errors.add(new ErrorDetail(customCode, fieldError.getDefaultMessage(), fieldError.getField())); } return new ResponseEntity<>(new ErrorResponse(errors), HttpStatus.BAD_REQUEST); } // 处理路径/请求参数验证异常 @ExceptionHandler(ConstraintViolationException.class) public ResponseEntity<ErrorResponse> handleParamValidation(ConstraintViolationException ex) { List<ErrorDetail> errors = new ArrayList<>(); for (ConstraintViolation<?> violation : ex.getConstraintViolations()) { String constraintName = violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName(); String customCode = CONSTRAINT_ERROR_CODE_MAP.getOrDefault(constraintName, constraintName); String field = violation.getPropertyPath().toString(); errors.add(new ErrorDetail(customCode, violation.getMessage(), field)); } return new ResponseEntity<>(new ErrorResponse(errors), HttpStatus.BAD_REQUEST); } // 错误响应结构类 public static class ErrorResponse { private List<ErrorDetail> errors; public ErrorResponse(List<ErrorDetail> errors) { this.errors = errors; } public List<ErrorDetail> getErrors() { return errors; } public void setErrors(List<ErrorDetail> errors) { this.errors = errors; } } // 错误详情类 public static class ErrorDetail { private String code; private String message; private String field; public ErrorDetail(String code, String message, String field) { this.code = code; this.message = message; this.field = field; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getField() { return field; } public void setField(String field) { this.field = field; } } }
通过上述代码,即可将默认的DecimalMax、DecimalMin错误码替换为自定义的100、101数字码,同时保留原有的错误消息和字段信息。
内容的提问来源于stack exchange,提问作者jcrshankar
相关产品推荐
相关产品推荐

