Spring Boot升级后,Jackson序列化无效

时间:2017-12-16 12:38:21

标签: java spring spring-boot jackson hateoas

昨天我开始从Spring Brussels-SR3升级到Spring Brussels-SR6 Spring Boot从1.5.4开始。到1.5.9,杰克逊从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字段更改为“链接”...所以不使用_halObjectMapper继续序列化。

任何线索可能是什么问题,或者我应该在哪里挖掘以找出问题所在?

调试后的其他信息:

我已经发现使用_halObjectMapper的TypeConstrainedMappingJackson2HttpMessageConverter不再用于转换为json。原因是它在启动弹簧时无法进入转换器集合。看起来它不是为RequestMappingHandlerAdapter bean创建的,因为当某些其他转换器(在本例中为ProjectingJackson2HttpMessageConverter)中已经注册了Jackson2HalModule时跳过创建的某些条件。

任何想法可能是什么原因或在哪里查看以确定弹簧启动开始的原因不同?

进行更多调试后的其他信息:

我在升级之前和之后看到的差异是,在升级之前,ProjectingJackson2HttpMessageConverter填充了新的ObjectMapper实例。但是在升级之后,ObjectMapper从容器中解析出来,因此选择了_halObjectMapper。因此,ProjectingJackson2HttpMessageConverter匹配为具有已注册halModule的转换器,并且对RequestMappingHandlerAdapter省略了TypeConstrainedMappingJackson2HttpMessageConverter创建。

另一个有趣的事情是我升级了另外两个微服务。不同的是,一个人有同样的问题,一个是有效的。正在工作的那个有不同的弹簧安全性和oauth2设置。 OAuth2RestTemplate类的Bean未在工作的微服务中定义。使用OAuth2RestTemplate的微服务存在问题。我之所以指出这一点,是因为在这两种情况下初始化行为有所不同。 OAuth2RestTemplate rest模板也填充了这些转换器,它可能会影响初始化过程。

临时解决方案

作为临时修补程序,我已将spring-data-commons从1.13.6.RELEASE降级为1.13.6.RELEASE。然而,较新的代码对我来说更有意义。

我仍在尝试更好地理解并找出正确的方法

1 个答案:

答案 0 :(得分:0)

我不知道它是否对您有帮助,但是从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;
    }
}

可以通过apps.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-objectmapperhttps://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html