如何处理Spring Boot Rest和Jackson反序列化器Javax验证中的无效数字

如何处理Spring Boot Rest和Jackson反序列化器Javax验证中的无效数字,java,spring-boot,validation,jackson,spring-restcontroller,Java,Spring Boot,Validation,Jackson,Spring Restcontroller,我有一个Java Pojo类,它在我的Rest控制器中应该是@RequestBody。这个JavaPOJO类有一个整数字段 当用户调用RESTAPI并将整型字段值作为垃圾字符串传递时,Jackson抛出了InvalidFormatException。相反,我想使用javaxvalidator框架注释来处理这个错误,并在响应中显示一条有意义的错误消息。不幸的是,Jackson从JSON到Java的反序列化发生在Javax验证之前,因此从未调用我的@Digits验证 注意,@NotNull会被调用,

我有一个Java Pojo类,它在我的Rest控制器中应该是
@RequestBody
。这个JavaPOJO类有一个整数字段

当用户调用RESTAPI并将整型字段值作为垃圾字符串传递时,Jackson抛出了
InvalidFormatException
。相反,我想使用javaxvalidator框架注释来处理这个错误,并在响应中显示一条有意义的错误消息。不幸的是,Jackson从JSON到Java的反序列化发生在Javax验证之前,因此从未调用我的
@Digits
验证

注意,@NotNull会被调用,但@Digits不会被调用,因为jackson在调用到达Javax验证层IMO之前很久就失败了请求

Java Pojo类:

控制器类:

@Controller
@RequestMapping("boards")
public class EnrichController {

    @Autowired
    private BoardService boardService;

    @RequestMapping(value = "", method = RequestMethod.PUT, produces = "application/json;charset=UTF-8")
    public @ResponseStatus(value = HttpStatus.NO_CONTENT) @ResponseBody void updateBoard(
            @RequestBody @Valid Board board) throws IllegalArgumentException, MalformedURLException {
        boardService.updateUserBoard(board);
    }
}
用户输入:

{
  "quantity": "abcdef"
}
正如您所看到的,我正在使用Javax验证注释
@Digits
&
@Valid
,但没有任何用处,因为Jackson反序列化在解析整数字段
quantity
时失败


您是否可以通过使用Javax验证注释处理这个用例来帮助我解决这个问题?我认为在POJO类中将字段类型更改为字符串是一项昂贵的工作,因为每当我需要该字段的一些业务逻辑时,我们都必须进行字符串到整数的转换,因此,这对我来说不是一个选项。

在您的情况下,问题是您不符合公开的REST API,并尝试发送一个字符串而不是数量字段的数字。无论是您还是使用API的第三方服务都不应该发生这种情况

您是否可以通过使用Javax验证注释处理这个用例来帮助我解决这个问题

在任何情况下,如果您仍然想要修复上述问题,解决方案是更改字符串类型字段中的“数量”,并为其添加模式匹配

@Pattern(message = "quantity must be a number", regexp="^[0-9]*$")
private String quantity;

谢谢,但将Pojo字段从整数转换为字符串相当昂贵。我负担不起,因为每次需要业务逻辑代码时都需要手动进行转换。我更想知道是否存在框架级支持,可以绕过特定字段上的Jackson解析错误,而是在Javax验证层处理它。不客气。我同意你的观点,这就是为什么我认为你不应该太在意绕过Jackson,因为如果有人以这种方式调用你的API,那么他们就是在做错事,不尊重你的API结构。但是,如果你正在与一个系统集成,并且你确信他们正在以这种方式发送数据,并且数据不会很快被更改,那么唯一的解决方案就是将其更改为字符串。之后,您可以使用来简化转换过程。在
Board
参数旁边添加一个
BindingResult
,以捕获错误并在控制器内进行处理。或者编写一个
@ExceptionHandler
来提供正确的错误消息。谢谢@M.Deinum,我已经在ControllerAdvice类中尝试了@ExceptionHandler,但它没有满足我在Javax验证层中处理这个特定用例的要求。在这种情况下,错误总是由Jackson解析器处理的,并且总是这样,除非您将类型更改为
String
,并将其验证为数字。无法将非整数指定给整数进行验证。您想要在当前设置中实现什么是不可能的。因此,基本上,该值是分配给pojo的,并且只有在验证之后才运行?这太难看了。我本以为在尝试分配值之前会运行验证,然后这个场景就会完美地运行。愚蠢的spring验证:(实际上,如果你发送一个字符串,至少它不应该分配一个数字,你可以验证NotNull,对吗?
@Pattern(message = "quantity must be a number", regexp="^[0-9]*$")
private String quantity;