请求校验失败后Jackson序列化报错,如何让其忽略@Size校验?
Hey there! I’ve run into this exact headache before—Jackson throwing that annoying JsonProcessingException with "Error(s) validating object" when you try to serialize a request object that failed JSR-380 validation (like @Size checks). Let’s break down why this happens and how to fix it.
Why This Occurs
By default, Jackson’s BeanValidationModule runs validation both during deserialization and serialization. So even if you’ve already used @Valid/@Validated in your controller to catch invalid requests, when you try to serialize that same invalid object in your error response, Jackson re-runs the validation and throws the exception.
Solution 1: Disable Jackson’s Serialization-Time Validation Globally
If you don’t need Jackson to handle validation (since you’re already doing it via Spring’s validation annotations), you can turn off this behavior for all serializations.
For Spring Boot Apps
Create a custom ObjectMapper bean that disables validation entirely:
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); BeanValidationModule validationModule = new BeanValidationModule(); // Tell Jackson to skip validation during serialization/deserialization validationModule.setValidationMode(ValidationMode.NONE); mapper.registerModule(validationModule); return mapper; } }
Solution 2: Use a Validation-Skipping ObjectMapper in Your Exception Handler
If you don’t want to disable validation globally, create a dedicated ObjectMapper just for serializing invalid objects in your error responses. This keeps regular serialization behavior intact while fixing the error response case.
Here’s how to implement this in a Spring global exception handler:
@RestControllerAdvice public class GlobalValidationExceptionHandler { // ObjectMapper that skips validation during serialization private final ObjectMapper validationSkippingMapper; public GlobalValidationExceptionHandler() { validationSkippingMapper = new ObjectMapper(); BeanValidationModule module = new BeanValidationModule(); module.setValidationMode(ValidationMode.NONE); validationSkippingMapper.registerModule(module); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ValidationErrorResponse> handleValidationErrors(MethodArgumentNotValidException ex) { // Get the original invalid request object Object invalidRequest = ex.getBindingResult().getTarget(); // Extract human-readable validation errors List<String> errorDetails = ex.getBindingResult() .getFieldErrors() .stream() .map(error -> String.format("%s: %s", error.getField(), error.getDefaultMessage())) .collect(Collectors.toList()); // Serialize the invalid request without triggering validation String requestJson; try { requestJson = validationSkippingMapper.writeValueAsString(invalidRequest); } catch (JsonProcessingException e) { // Fallback if serialization still fails (use toString() as backup) requestJson = invalidRequest.toString(); } // Build your error response ValidationErrorResponse response = new ValidationErrorResponse(); response.setRequestContent(requestJson); response.setErrors(errorDetails); response.setMessage("Request failed parameter validation"); return ResponseEntity.badRequest().body(response); } // Inner class for your error response structure static class ValidationErrorResponse { private String requestContent; private List<String> errors; private String message; // Getters and setters public String getRequestContent() { return requestContent; } public void setRequestContent(String requestContent) { this.requestContent = requestContent; } public List<String> getErrors() { return errors; } public void setErrors(List<String> errors) { this.errors = errors; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } }
Key Notes
- Make sure you’re using
@Validor@Validatedon your controller method parameters to trigger validation early (before reaching serialization). This ensures you catch the error at the input stage, not during response building. - The fallback
toString()in the exception handler is a safety net—most of the time, the validation-skippingObjectMapperwill work, but it’s good to have a backup.
内容的提问来源于stack exchange,提问作者Raoul Duke




