java - Spring Boot 升级后 Jackson 序列化不起作用

标签 java spring spring-boot jackson hateoas

昨天我开始从 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-objectmapperhttps://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

关于java - Spring Boot 升级后 Jackson 序列化不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47845755/

相关文章:

java - Selenium WebDriver + java .通过类名定位

java - Ajax 表单提交和文件上传不起作用 Spring MVC

Java批量导入

java - 如何使用 Maven 检查缺少的 @Override 注释

java - Spring boot AMQP并发监听器顺序执行?

java - 在嵌入式数据库中为 Spring Batch 创建元数据表

spring-boot - SpringBoot,Thymeleaf,Gradle:未访问静态资源,CSS未显示

java - 寻找一个框架/模式来处理特定数据集的更改

java - 由 : org. apache.logging.log4j.LoggingException 引起:log4j-slf4j-impl cannot be present with log4j-to-slf4j

java - Spring集成UDP服务器不监听