简体   繁体   中英

Spring Boot annotation validation get index from list

I have a rest application (no forms, etc.) with the following request mapping for the input:

public class User {
    @Valid
    private List<Contact> contact;

    public List<Contact> getContact() {
        return contact;
    }

    public void setContact(List<Contact> contact) {
        this.contact = contact;
    }
}


public class Contact {
    @Size(max = 20, message = ErrorMessages.E_MAIL_INVALID_LENGTH)
    private String email;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

The validation works but I also want to include the index of the item where it violated a constraint:

actual input and response:

{
        "contact" :[{
            "email": "tesaaaaaaaaaaaaaaaaaaaaaaaaaaaat@test.com"
        },       {
            "email": "tesaaaaaaaaaaaaaaaaaaaaaaaaaaaat@test.com"
        }
        ]
}




{
    "timestamp": "2022-06-16T00:43:50.878+00:00",
    "status": 400,
    "errors": [
        "E-mail address 'tesaaaaaaaaaaaaaaaaaaaaaaaaaaaat@test.com' must be between 0 and 20 characters long",
        "E-mail address 'tesaaaaaaaaaaaaaaaaaaaaaaaaaaaat@test.com' must be between 0 and 20 characters long"
    ]
}

for the response I want to generate I want to put the index like this:

E-Mail address 1 E-Mail address 2

{
    "timestamp": "2022-06-16T00:43:50.878+00:00",
    "status": 400,
    "errors": [
        "E-mail address 1: 'tesaaaaaaaaaaaaaaaaaaaaaaaaaaaat@test.com' must be between 0 and 20 characters long",
        "E-mail address 2: 'tesaaaaaaaaaaaaaaaaaaaaaaaaaaaat@test.com' must be between 0 and 20 characters long"
    ]
}

UPDATE

I got it to work by using the following code in my controller ()

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Map<String, Object> handleValidationExceptions(MethodArgumentNotValidException ex) {

        Map<String, Object> body = new LinkedHashMap<>();
        body.put("timestamp", new Date());
        body.put("status", HttpStatus.BAD_REQUEST);

        Map<String, String> errors = new HashMap<>();
        List<ObjectError> errorList = ex.getBindingResult().getAllErrors();

        errorList.forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });

        body.put("errors", errors);

        return body;
    }

output is:

{
    "timestamp": "2022-06-16T01:49:04.832+00:00",
    "status": "BAD_REQUEST",
    "errors": {
        "contact[1].email": "E-mail address 'tesaaaaaaaaaaaaaaaaaaaaaaaaaaaat@test.com' must be between 0 and 20 characters long",
        "contact[0].email": "E-mail address 'tesaaaaaaaaaaasdasdasdaaaaaaaaaaaaaaaaat@test.com' must be between 0 and 20 characters long"
    }
}

I just need to reverse the order of the error messages and it's all good.

You can try using a counter variable, which can work as an index for each error.

First create a counter variable before the forEach then use it inside the forEach .

Here is the updated Controller'a code.

@ResponseStatus(HttpStatus.BAD_REQUEST)
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public Map<String, Object> handleValidationExceptions(MethodArgumentNotValidException ex) {

        Map<String, Object> body = new LinkedHashMap<>();
        body.put("timestamp", new Date());
        body.put("status", HttpStatus.BAD_REQUEST);

        Map<String, String> errors = new HashMap<>();
        List<ObjectError> errorList = ex.getBindingResult().getAllErrors();

        int counter = 0;

        errorList.forEach((error) -> {
            counter++;
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            String index = String.valueOf(counter);
            errors.put(index, fieldName, errorMessage);
        });

        body.put("errors", errors);

        return body;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM