You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

请求校验失败后Jackson序列化报错,如何让其忽略@Size校验?

Fixing Jackson's JsonProcessingException When Serializing Validation-Failed Objects

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 @Valid or @Validated on 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-skipping ObjectMapper will work, but it’s good to have a backup.

内容的提问来源于stack exchange,提问作者Raoul Duke

火山引擎 最新活动