昨天我开始从 Spring Brussels-SR3 升级到 Spring Brussels-SR6。
Spring Boot 从 1.5.4 开始。到 1.5.9,Jackson 从 2.8.8 到 2.8.10)。我正在使用 HATEOAS 和 HAL 链接。这意味着我的 Jackson 配置如下所示:
@Configuration
public class JacksonConfiguration {
private static final String SPRING_HATEOAS_OBJECT_MAPPER = "_halObjectMapper";
@Autowired
@Qualifier(SPRING_HATEOAS_OBJECT_MAPPER)
private ObjectMapper springHateoasObjectMapper;
@Primary
@Bean(name = "objectMapper")
ObjectMapper objectMapper() {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(ZonedDateTime.class, new ZonedDateTimeSerializer(DateTimeFormatter.ISO_INSTANT));
springHateoasObjectMapper.registerModules(javaTimeModule);
springHateoasObjectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
springHateoasObjectMapper.disable(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS);
springHateoasObjectMapper.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS);
springHateoasObjectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
springHateoasObjectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
springHateoasObjectMapper.enable(SerializationFeature.INDENT_OUTPUT);
springHateoasObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
return springHateoasObjectMapper;
}
}
这意味着我正在重用 _halObjectMapper
bean 并添加更多配置。在我开始升级之前,它一直在工作。
怎么了?
问题是升级后我所有的序列化自定义和 HAL 约定都没有应用 - 日期时间格式,缩进 HAL “_links”
JSON 字段更改为“links”......所以_halObjectMapper 不再用于序列化。
任何线索可能是什么问题,或者我应该在哪里挖掘以找出问题所在?
一些调试后的附加信息:
我发现使用 _halObjectMapper 的 TypeConstrainedMappingJackson2HttpMessageConverter 不再用于转换为 json。原因是启动spring的时候没有到达converters的集合。看起来它不是为 RequestMappingHandlerAdapter bean 创建的,因为当 Jackson2HalModule 已经在其他转换器(在本例中为 ProjectingJackson2HttpMessageConverter)中注册时,某些条件会跳过创建。
知道可能是什么原因或在哪里可以弄清楚为什么 spring boot 启动以不同方式进行吗?
更多调试后的附加信息:
我在升级前后看到的区别是,在升级之前,ProjectingJackson2HttpMessageConverter 填充了 ObjectMapper 的新实例。但是在升级之后,ObjectMapper 是从容器中解析出来的,所以选择了 _halObjectMapper。因此,ProjectingJackson2HttpMessageConverter 匹配为具有已注册 halModule 的转换器,并且 TypeConstrainedMappingJackson2HttpMessageConverter 的创建被 RequestMappingHandlerAdapter 省略。
更有趣的是,我升级了两个微服务。不同之处在于,一个有同样的问题,一个正在工作。正在工作的那个具有不同的 spring security 和 oauth2 设置。正在运行的微服务中未定义类 OAuth2RestTemplate 的 Bean。带有 OAuth2RestTemplate 的微服务有问题。我之所以指出这一点,是因为这两种情况下的初始化行为不同。 OAuth2RestTemplate rest 模板也填充了这些转换器,它可能会影响初始化过程。
临时解决方案
作为临时修补程序,我已将 spring-data-commons 从 1.13.6.RELEASE 降级为 1.13.6.RELEASE。然而,较新的代码对我来说更有意义。
我仍在努力获得更好的理解并找出正确的方法
最佳答案
我不知道它是否对你有帮助,但我在将 Spring Boot 从版本 2.0.3 升级到 2.0.4 时遇到了非常相似的问题。我仍然不知道到底是什么导致了这个问题,但解决方案是为我使用的每个模块创建 Bean,而不是替换默认的 ObjectMapper。在您的情况下,它看起来像这样:
@Configuration
public class JacksonConfiguration {
@Bean
JavaTimeModule javaTimeModule () {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(ZonedDateTime.class, new ZonedDateTimeSerializer(DateTimeFormatter.ISO_INSTANT));
return javaTimeModule;
}
}
所有功能都可以通过 applications.properties 文件进行设置,如下所示:
spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=false
spring.jackson.deserialization.READ_DATE_TIMESTAMPS_AS_NANOSECONDS=false
等等。有关如何配置默认对象映射器而不实际替换它的更多信息,请参阅 https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-customize-the-jackson-objectmapper和 https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
关于java - Spring Boot 升级后 Jackson 序列化不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47845755/