升级Jackson后未在接口定义的getter未被序列化如何恢复旧版本行为
问题原因
从Jackson 2.6升级到2.10+、Spring 4.x升级到5.x后出现该问题,是两个框架的默认配置变更共同导致的:
- Spring 5.x调整了
MappingJackson2HttpMessageConverter的默认逻辑,处理Controller返回值时,会将方法声明的返回值静态类型(也就是你代码里的Interface A)作为序列化目标类型传递给Jackson,而Spring 4.x版本默认不会显式传递该类型。 - Jackson 2.7+版本优化了类型解析逻辑,当收到显式指定的序列化目标类型时,会仅扫描该目标类型下定义的可序列化字段、getter方法,不会自动扫描运行时实际实现类(B/C/D)的额外方法,因此Interface A中未定义的getter都会被忽略。
修复方案
不需要修改业务接口定义,可选以下任意一种方案即可恢复旧版本序列化行为:
方案1:全局调整Jackson配置(推荐)
在Spring MVC配置中自定义Jackson的ObjectMapper,关闭静态类型检测开关,强制Jackson使用运行时实际类型扫描可序列化属性:
import com.fasterxml.jackson.databind.MapperFeature; 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 JacksonConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 自定义ObjectMapper MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(); jacksonConverter.getObjectMapper().disable(MapperFeature.USE_STATIC_TYPING); // 把自定义Converter放在列表首位,优先生效 converters.add(0, jacksonConverter); } }
如果你的项目中已经有全局注册的ObjectMapper Bean,直接在该Bean的配置中添加disable(MapperFeature.USE_STATIC_TYPING)即可。
方案2:仅修改对应Controller方法
如果不想全局修改配置,只需将出现问题的Controller接口的返回值类型改为Object,Spring MVC就不会向Jackson传递静态类型,Jackson会自动识别运行时实际类型完成序列化。
方案3:针对Interface A配置混合注解
如果需要限制生效范围仅为Interface A及其实现类,不需要全局修改,可以为Interface A配置Jackson混合注解:
// 首先在ObjectMapper配置中添加混合注解绑定 jacksonConverter.getObjectMapper().addMixIn(A.class, UseRuntimeTypeMixin.class); // 定义混合注解类 public abstract class UseRuntimeTypeMixin { @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) }
内容的提问来源于stack exchange,提问作者Lucian
相关产品推荐
相关产品推荐

