问题
I know there is some similar questions here about how to parse ENUM, how to parse customize JSON structure. But here my question is how to just give a better message when the user submit some JSON with is not as expected.
This is the code:
@PutMapping
public ResponseEntity updateLimitations(@PathVariable("userId") String userId,
@RequestBody LimitationParams params) {
Limitations limitations = user.getLimitations();
params.getDatasets().forEach(limitations::updateDatasetLimitation);
params.getResources().forEach(limitations::updateResourceLimitation);
userRepository.save(user);
return ResponseEntity.noContent().build();
}
And the request body I expected is like this:
{
"datasets": {"public": 10},
"resources": {"cpu": 2}
}
But when they submit something like this:
{
"datasets": {"public": "str"}, // <--- a string is given
"resources": {"cpu": 2}
}
The response will show something like this in logs:
400 JSON parse error: Cannot deserialize value of type `java.lang.Integer` from String "invalid": not a valid Integer value; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.lang.Integer` from String "invalid": not a valid Integer value
at [Source: (PushbackInputStream); line: 1, column: 23] (through reference chain: com.openbayes.api.users.LimitationParams["datasets"]->java.util.LinkedHashMap["public"])
But what I want is a more human readable message.
I tried to use ExceptionHandler
for com.fasterxml.jackson.databind.exc.InvalidFormatException
but it doesn't work.
回答1:
You can write a controller advice to catch exceptions and return corresponding error response.
Here is an example of controller advice in spring boot :
@RestControllerAdvice
public class ControllerAdvice {
@ExceptionHandler(InvalidFormatException.class)
public ResponseEntity<ErrorResponse> invalidFormatException(final InvalidFormatException e) {
return error(e, HttpStatus.BAD_REQUEST);
}
private ResponseEntity <ErrorResponse> error(final Exception exception, final HttpStatus httpStatus) {
final String message = Optional.ofNullable(exception.getMessage()).orElse(exception.getClass().getSimpleName());
return new ResponseEntity(new ErrorResponse(message), httpStatus);
}
}
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ErrorResponse {
private String errorMessage;
}
回答2:
The real exception is org.springframework.http.converter.HttpMessageNotReadableException. Intercept this and it will work.
public ResponseEntity<String> handle(HttpMessageNotReadableException e) {
return ResponseEntity.badRequest().body("your own message" + e.getMessage());
}
回答3:
Following error handling method is worked for me.
@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity handleAllOtherErrors(HttpMessageNotReadableException formatException) {
String error = formatException.getMessage().toString();
return new ResponseEntity(error, HttpStatus.BAD_REQUEST);
来源:https://stackoverflow.com/questions/52196053/how-to-handle-jackson-deserialization-error-for-all-kinds-of-data-mismatch-in-sp