Can @Valid be used with @HashMap generated from JSON payload?

I am trying to use spring-mvc @Valid

next to mine @RequestBody

to check if my json payload has a given parameter.

I've found solutions that use binding, but it's almost like calling validation in your method @RequestMapping

. I also found a way to use @Valid

when you have the expected payload.

My payload is fully dynamic and I only want to check if a field exists, eg id

. My current handler:

@RequestMapping(method = RequestMethod.POST, value="/path", consumes = "application/json")
    @ResponseBody
    @Valid
    public Object get(final HttpServletRequest request, @Valid @RequestBody HashMap payload ) {

      

Since my payload is fully dynamic, I created HashMap

to hold it. I was wondering if I could use @NotEmpty

or a similar annotation if I add HashMap

to a custom class that just checks if the property exists.

Am I on the right track? Is this not possible for dynamic payloads?

Thanks in advance.

+3


source to share


1 answer


Question: yes and no.

Yes , you can use @Valid

to request verification.

No , you cannot use a simple @NotEmpty

for a property, as you need a specific DTO for this purpose.

Considering the payload is dynamic, the best thing I could do was based on @EddieB 's tutorial link and it goes like this.

Same function header as mine in the question

    @RequestMapping(method = RequestMethod.POST, value="/path", consumes = "application/json")
    @ResponseBody
    public Object get(final HttpServletRequest request, @Valid @RequestBody HashMap payload ) {

      

But since the payload is dynamic, in this case the HashMap you need some custom validation. The cleanest way I found was to use annotation @InitBinder

to attach Validator

to this request @Valid

.



   // instantiated in the constructor
    private final MyValidator myValidator

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(this.myValidator);
    }

      

And then our custom validator:

public class MyValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
        return HashMap.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
       // do your custom validation.
       // if you don't call error.reject* it is considered a valid argument
    }

      

If you make a mistake, you will catch it by creating a @ControllerAdvice

. In my case, I explicitly set @ResponseStatus

to BAD_REQUEST

, as if it got here, this is definitely caused by a bad payload:

@ControllerAdvice
public class MyHandler{

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public String processValidationError(MethodArgumentNotValidException exception) {
        // custom error handling
    }
}

      

Thanks to both members for the comments that led me to this answer.

+3


source







All Articles