SpringBoot仅对外接口启用Jackson未知字段反序列化失败限制
解决方案:仅对面向客户的控制器请求体启用未知字段校验
要实现仅在面向客户的控制器请求体反序列化时强制执行fail-on-unknown-fields,而其他场景(如调用应用Y的API)忽略未知字段,可以采用以下几种方案,根据实际情况选择:
方案一:在DTO类上直接配置(最简单)
直接在面向客户的DTO类上添加@JsonIgnoreProperties(ignoreUnknown = false)注解,让Jackson反序列化该类时严格校验未知字段,全局Jackson配置保持默认的fail-on-unknown-properties=false(忽略未知字段)即可。
修改你的Product类:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = false) class Product { private int id; private String name; private int price; // 省略getter、setter、构造方法 }
当客户传入包含colour的请求体时,Jackson会抛出UnrecognizedPropertyException,Spring Boot会自动将其转换为400 Bad Request响应,完全符合需求。
这种方式优势是精准控制单个DTO,不会影响其他场景的反序列化(比如调用应用Y的API时使用的其他DTO类,不加该注解就会忽略未知字段)。
方案二:全局拦截面向客户的控制器请求(批量处理)
如果有大量面向客户的控制器和DTO,不想逐个添加注解,可以通过实现RequestBodyAdvice统一为指定包下的控制器请求启用严格校验。
步骤1:创建自定义RequestBodyAdvice
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.core.MethodParameter; import org.springframework.http.HttpInputMessage; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter; import java.io.IOException; import java.lang.reflect.Type; // 指定面向客户的控制器所在的包路径 @ControllerAdvice(basePackages = "com.yourproject.controller.client") public class ClientRequestBodyValidationAdvice extends RequestBodyAdviceAdapter { @Override public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) { // 只处理JSON类型的消息转换器 return MappingJackson2HttpMessageConverter.class.isAssignableFrom(converterType); } @Override public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException { // 创建全局ObjectMapper的副本,避免修改全局配置影响其他场景 ObjectMapper strictMapper = ((MappingJackson2HttpMessageConverter) converterType.getDeclaredConstructor().newInstance()).getObjectMapper().copy(); // 启用未知字段失败校验 strictMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); // 替换消息转换器的ObjectMapper为严格校验版本 MappingJackson2HttpMessageConverter strictConverter = new MappingJackson2HttpMessageConverter(strictMapper); return new HttpInputMessage() { @Override public java.io.InputStream getBody() throws IOException { return inputMessage.getBody(); } @Override public org.springframework.http.HttpHeaders getHeaders() { return inputMessage.getHeaders(); } }; } }
说明
@ControllerAdvice(basePackages = "...")指定只对该包下的控制器生效,避免影响内部API的控制器。- 复制全局ObjectMapper的副本进行修改,确保全局配置不受影响,调用应用Y的API时依然忽略未知字段。
方案三:为控制器单独配置消息转换器
如果需要更细粒度的控制,可以为面向客户的控制器单独配置一个带有严格校验的Jackson消息转换器:
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration public class ClientWebMvcConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 创建严格校验的ObjectMapper ObjectMapper strictObjectMapper = new ObjectMapper(); strictObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); // 同步全局Jackson的其他配置(如日期格式化、模块注册) strictObjectMapper.findAndRegisterModules(); // 创建自定义消息转换器并优先使用 MappingJackson2HttpMessageConverter strictConverter = new MappingJackson2HttpMessageConverter(strictObjectMapper); converters.add(0, strictConverter); } }
如果只想让该转换器对特定控制器生效,可以结合@ControllerAdvice和RequestMappingHandlerAdapter来注入转换器。
内容的提问来源于stack exchange,提问作者Victoriia
相关产品推荐
相关产品推荐

