@RequestBody @Valid SomeDTO 具有枚举类型的字段,自定义错误消息

tim*_*ham 9 java validation rest spring

我有以下 @RestController

@RequestMapping(...)
public ResponseEntity(@RequestBody @Valid SomeDTO, BindingResult errors) {
//do something with errors if validation error occur
}

public class SomeDTO {
   public SomeEnum someEnum;
}
Run Code Online (Sandbox Code Playgroud)

如果 JSON 请求是{ "someEnum": "valid value" },则一切正常。但是,如果请求是{ "someEnum": "invalid value" },则只返回错误代码 400。

如何捕获此错误,以便我可以提供自定义错误消息,例如“someEnum 的值必须为 A/B/C”。

Aru*_*wda 10

@Amit 提供的答案很好并且有效。如果您想以特定方式反序列化枚举,您可以继续这样做。但该解决方案不可扩展。因为每个需要验证的枚举都必须用 进行注释@JsonCreator

其他答案不会帮助您美化错误消息。

所以这是我的解决方案,适用于 Spring Web 环境中的所有枚举。

@RestControllerAdvice
public class ControllerErrorHandler extends ResponseEntityExceptionHandler {
    public static final String BAD_REQUEST = "BAD_REQUEST";
    @Override
    public ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException exception,
                                                               HttpHeaders headers, HttpStatus status, WebRequest request) {
        String genericMessage = "Unacceptable JSON " + exception.getMessage();
        String errorDetails = genericMessage;

        if (exception.getCause() instanceof InvalidFormatException) {
            InvalidFormatException ifx = (InvalidFormatException) exception.getCause();
            if (ifx.getTargetType()!=null && ifx.getTargetType().isEnum()) {
                errorDetails = String.format("Invalid enum value: '%s' for the field: '%s'. The value must be one of: %s.",
                        ifx.getValue(), ifx.getPath().get(ifx.getPath().size()-1).getFieldName(), Arrays.toString(ifx.getTargetType().getEnumConstants()));
            }
        }
        ErrorResponse errorResponse = new ErrorResponse();
        errorResponse.setTitle(BAD_REQUEST);
        errorResponse.setDetail(errorDetails);
        return handleExceptionInternal(exception, errorResponse, headers, HttpStatus.BAD_REQUEST, request);
    }

}
Run Code Online (Sandbox Code Playgroud)

这将处理所有类型的所有无效枚举值,并为最终用户提供更好的错误消息。

示例输出:

{
    "title": "BAD_REQUEST",
    "detail": "Invalid enum value: 'INTERNET_BANKING' for the field: 'paymentType'. The value must be one of: [DEBIT, CREDIT]."
}
Run Code Online (Sandbox Code Playgroud)


Ama*_*eep 1

Yon 可以使用 @ControllerAdvice以下方法 实现这一点

@org.springframework.web.bind.annotation.ExceptionHandler(value = {InvalidFormatException.class})
    public ResponseEntity handleIllegalArgumentException(InvalidFormatException exception) {

        return ResponseEntity.badRequest().body(exception.getMessage());
    }
Run Code Online (Sandbox Code Playgroud)

com.fasterxml.jackson.databind.exc.InvalidFormatException基本上,这个想法是根据您的要求捕获并处理它。