Spring Boot 自定义Jackson ObjectMapper

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot 自定义Jackson ObjectMapper相关的知识,希望对你有一定的参考价值。

参考技术A 在Spring Boot Web 项目中,当使用JSON格式接收数据和返回数据的时候,Spring Boot 默认使用一个ObjectMapper实例来序列化响应和反序列化请求。

在本文中,我们将看看配置序列化和反序列化选项的最常用方法。

默认情况下,Spring Boot的配置将禁用以下配置项。

举个例子

我们将通过使用String和LocalDateTime对象来示范定制选项。

我们还将定义一个简单的REST控制器来演示序列化。

默认情况下,这将是调用GET http://lolcahost:8080/coffee?brand=javazzz 时的响应。

我们希望排除空值,并有一个自定义的日期格式(dd-MM-yyyy HH:mm)。这就是我们的响应结果。

在使用Spring Boot时,我们可以选择定制默认的ObjectMapper或覆盖它。我们将在接下来的章节中介绍这两个选项。

在本节中,我们将看到如何定制Spring Boot使用的默认ObjectMapper。

配置映射器的最简单方法是通过应用程序属性。

下面是配置的一般结构。

作为一个例子,下面是我们要添加的内容,以禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS。

除了提到的特征类别,我们还可以配置属性的包含。

配置环境变量是最简单的方法。这种方法的缺点是,我们不能定制高级选项,比如为LocalDateTime定制日期格式。

在这一点上,我们会得到这样的结果。

为了实现我们的目标,我们将注册一个新的JavaTimeModule,用我们的自定义日期格式。

另外,配置属性文件coffee.properties将包含以下内容。

Spring Boot会自动注册任何类型为com.fastxml.jackson.databind.Module的bean。下面是我们的最终结果。

这个功能接口的目的是让我们创建配置。

它们将被应用于通过Jackson2ObjectMapperBuilder创建的默认ObjectMapper。

配置得以特定的顺序应用,我们可以使用@Order annotation来控制。如果我们想从不同的配置或模块来配置ObjectMapper,这种优雅的方法是适合的。

如果我们想完全控制配置,有几个选项可以禁用自动配置,只允许应用我们的自定义配置。

让我们仔细研究一下这些选项。

覆盖默认配置的最简单方法是定义一个ObjectMapper Bean并将其标记为@Primary。

当我们想完全控制序列化过程而不想允许外部配置时,我们应该使用这种方法。

另一种干净的方法是定义一个Jackson2ObjectMapperBuilderbean。

实际上,Spring Boot在构建ObjectMapper时默认使用这个构建器,并会自动拾取定义的构建器。

它将默认配置两个选项。

根据Jackson2ObjectMapperBuilder 文档,如果classpath上有一些模块,它也会注册这些模块。

这种方法的优点是,Jackson2ObjectMapperBuilder提供了一种简单而直观的方法来构建ObjectMapper。

我们可以直接定义一个类型为MappingJackson2HttpMessageConverter的bean,Spring Boot会自动使用它。

为了测试我们的配置,我们将使用TestRestTemplate并将对象序列化为String。

通过这种方式,我们可以验证我们的Coffee对象在序列化时没有null值,并且具有自定义的日期格式。

在这篇文章中,我们看了使用Spring Boot时配置JSON序列化选项的几种方法。

我们看到了两种不同的方法:配置默认选项或重写默认配置。

如何在 Spring Boot 1.4 中自定义 Jackson

【中文标题】如何在 Spring Boot 1.4 中自定义 Jackson【英文标题】:How to customise Jackson in Spring Boot 1.4 【发布时间】:2017-01-08 20:48:48 【问题描述】:

我一直无法找到如何在 spring boot 1.4 中使用 Jackson2ObjectMapperBuilderCustomizer.java 来自定义 Jackson 的功能的示例。

在 boot 1.4 中自定义 Jackson 的文档 - https://docs.spring.io/spring-boot/docs/1.4.x/reference/htmlsingle/#howto-customize-the-jackson-objectmapper

我的配置有效,但我不确定这是否是使用 Jackson2ObjectMapperBuilderCustomizer.java

自定义对象映射器的正确方法
@Configuration
public class JacksonAutoConfiguration 

    @Autowired
    private Environment env;

    @Bean
    public Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder(
        List<Jackson2ObjectMapperBuilderCustomizer> customizers) 
        Jackson2ObjectMapperBuilder builder = configureObjectMapper();
        customize(builder, customizers);
        return builder;
    

    private void customize(Jackson2ObjectMapperBuilder builder,
                           List<Jackson2ObjectMapperBuilderCustomizer> customizers) 
        for (Jackson2ObjectMapperBuilderCustomizer customizer : customizers) 
            customizer.customize(builder);
        
    

    private Jackson2ObjectMapperBuilder configureObjectMapper() 
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        List<String> activeProfiles = asList(env.getActiveProfiles());
        if (activeProfiles.contains(SPRING_PROFILE_DEVELOPMENT)) 
            builder.featuresToEnable(SerializationFeature.INDENT_OUTPUT);
        
        return builder;
    

为了提供一些上下文,这个类位于我自己的 REST 服务 spring 启动项目中,它只是自动配置一些东西,比如 ControllerAdvice 和一些像上面这样的琐碎功能。

所以我的目标是扩展 Jackson 配置,而不是覆盖 boot 或其他包提供的任何配置。

【问题讨论】:

【参考方案1】:

要自定义 Spring Boot 已经预配置的 Jackson ObjectMapper,我能够做到这一点(这里的示例是添加自定义反序列化器)。

配置类:

@SpringBootConfiguration
public class Application 

    @Autowired
    private BigDecimalDeserializer bigDecimalDeserializer;

    ...

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer addCustomBigDecimalDeserialization() 
        return new Jackson2ObjectMapperBuilderCustomizer() 

            @Override
            public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) 
                jacksonObjectMapperBuilder.deserializerByType(BigDecimal.class, bigDecimalDeserializer);
            

        ;
    

    ...


还有我的自定义反序列化器,以展示 Spring 是如何拾取它的:

@Component
public class BigDecimalDeserializer extends StdDeserializer<BigDecimal> 

    public BigDecimalDeserializer() 
        super(BigDecimal.class);
    

    @Override
    public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException 
        ...
    

    ...


【讨论】:

看准了!这是我最初尝试做的,但一定是做错了什么,谢谢。【参考方案2】:

这取决于你想要做什么。

如果除了默认执行的自定义之外,您还想进行一些自定义,那么您应该创建自己的 Jackson2ObjectMapperBuilderCustomizer 实现并将其公开为 bean。您目前拥有的是一个更复杂的版本。与其注入定制器然后自己调用它们,不如创建自己的定制器 bean,Boot 会为您调用它。

如果您想完全控制并关闭所有 Boot 的自定义设置,请创建一个 Jackson2ObjectMapperBuilderObjectMapper bean 并根据需要进行配置。构建器方法是首选,因为此构建器还用于配置由其他组件(如 Spring Data REST)创建的 ObjectMapper。

查看您的代码并退后一步,您可以通过使用特定于配置文件的配置文件(例如 application-dev.properties)来启用 Jackson 输出的缩进,从而更简单地进行配置。您可以阅读更多关于 here 的信息。

【讨论】:

谢谢这是我最初所做的,但它似乎没有效果。我明天会发布我的代码,也许你可以告诉我哪里没有错。至于您通过属性文件配置它的建议,我已经更新了我的问题,以提供更多关于我如何使用此配置类的上下文。【参考方案3】:

只需创建一个ObjectMapper bean:

@Bean
ObjectMapper objectMapper() 
    return Jackson2ObjectMapperBuilder
            .json()
            .featuresToEnable(MapperFeature.DEFAULT_VIEW_INCLUSION)
            .build();

【讨论】:

抱歉,我可能更清楚地表明我实际上是在扩展对象映射器功能。而您的建议实际上会覆盖任何 ObjectMapper bean,例如默认的一个 spring boot 配置 这对于 Spring Boot 来说不是很好的方法,因为可以有多个 jackson 定制器,并且返回构建的对象映射器实例使它们完全无用。

以上是关于Spring Boot 自定义Jackson ObjectMapper的主要内容,如果未能解决你的问题,请参考以下文章

在 Jackson / Spring Boot 中测试自定义 Json Deserializer

为啥使用 webflux 进行 spring boot 测试会忽略自定义 jackson 模块

Spring boot 拾遗 —— Spring Cache 使用 Jackson 与 自定义 TTL

Spring Boot 自定义Jackson ObjectMapper

Spring Boot - 自定义 JsonDeserializer 被忽略

Spring Boot - 自定义 JSON 序列化 [重复]