拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 Spring boot:自定义Jackson ObjectMapper

Spring boot:自定义Jackson ObjectMapper

白鹭 - 2021-11-24 733 0 0

1.概述

当使用JSON格式时,Spring Boot将使用ObjectMapper实例来序列化响应并反序列化请求。在本教程中,我们将介绍配置序列化和反序列化选项的最常用方法。

要了解有关Jackson的更多信息,请务必查看我们的Jackson教程。

2.默认配置

默认情况下,Spring Boot配置将:

  • 停用MapperFeature.DEFAULT_VIEW_INCLUSION
  • 禁用DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
  • 禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS

让我们从一个简单的例子开始:

  • 客户将向我们的/coffee?name=Lavazza发送一个GET请求/coffee?name=Lavazza
  • 控制器将返回一个新的Coffee对象
  • Spring将使用ObjectMapper将POJO序列化为JSON

我们将使用StringLocalDateTime对象举例说明自定义选项:

public class Coffee {



 private String name;

 private String brand;

 private LocalDateTime date;



 //getters and setters

 }

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

@GetMapping("/coffee")

 public Coffee getCoffee(

 @RequestParam(required = false) String brand,

 @RequestParam(required = false) String name) {

 return new Coffee()

 .setBrand(brand)

 .setDate(FIXED_DATE)

 .setName(name);

 }

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

{

 "name": null,

 "brand": "Lavazza",

 "date": "2020-11-16T10:21:35.974"

 }

我们想排除null值,并采用自定义日期格式(dd-MM-yyyy HH:mm)。最终答复将是:

{

 "brand": "Lavazza",

 "date": "04-11-2020 10:34"

 }

使用Spring Boot时,我们可以选择自定义默认的ObjectMapper或覆盖它。我们将在下一部分中介绍这两个选项。

3.自定义默认的ObjectMapper

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

3.1。应用程序属性和自定义Jackson模块

配置映射器的最简单方法是通过应用程序属性。配置的一般结构为:

spring.jackson.<category_name>.<feature_name>=true,false

例如,如果要禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS ,我们将添加:

spring.jackson.serialization.write-dates-as-timestamps=false

除了提到的功能类别,我们还可以配置属性包含:

spring.jackson.default-property-inclusion=always, non_null, non_absent, non_default, non_empty

配置环境变量是最简单的方法。这种方法的缺点是我们无法自定义高级选项,例如为LocalDateTime自定义日期格式。至此,我们将获得结果:

{

 "brand": "Lavazza",

 "date": "2020-11-16T10:35:34.593"

 }

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

@Configuration

 @PropertySource("classpath:coffee.properties")

 public class CoffeeRegisterModuleConfig {



 @Bean

 public Module javaTimeModule() {

 JavaTimeModule module = new JavaTimeModule();

 module.addSerializer(LOCAL_DATETIME_SERIALIZER);

 return module;

 }

 }

此外,配置属性文件coffee.properties将包含:

spring.jackson.default-property-inclusion=non_null

Spring Boot将自动注册com.fasterxml.jackson.databind.Module.类型的任何bean com.fasterxml.jackson.databind.Module.最终结果将是:

{

 "brand": "Lavazza",

 "date": "16-11-2020 10:43"

 }

3.2。 Jackson2ObjectMapperBuilderCustomizer

该功能接口的目的是允许我们创建配置bean。它们将应用于通过Jackson2ObjectMapperBuilder创建的默认ObjectMapper

@Bean

 public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {

 return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL)

 .serializers(LOCAL_DATETIME_SERIALIZER);

 }

配置Bean以特定顺序应用,我们可以使用@Order批注进行控制。如果我们要从不同的配置或模块配置ObjectMapper ,则这种优雅的方法非常适合。

4.覆盖默认配置

如果我们想完全控制配置,则有几个选项将禁用自动配置,并仅允许应用我们的自定义配置。让我们仔细看看这些选项。

4.1。 ObjectMapper

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

@Bean

 @Primary

 public ObjectMapper objectMapper() {

 JavaTimeModule module = new JavaTimeModule();

 module.addSerializer(LOCAL_DATETIME_SERIALIZER);

 return new ObjectMapper()

 .setSerializationInclusion(JsonInclude.Include.NON_NULL)

 .registerModule(module);

 }

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

4.2。 Jackson2ObjectMapperBuilder

另一个干净的方法是定义一个Jackson2ObjectMapperBuilder bean .实际上,默认情况下,Spring Boot在构建ObjectMapper时会使用此构建器,并且会自动选择定义的构建器:

@Bean

 public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {

 return new Jackson2ObjectMapperBuilder().serializers(LOCAL_DATETIME_SERIALIZER)

 .serializationInclusion(JsonInclude.Include.NON_NULL);

 }

默认情况下,它将配置两个选项:

  • 停用MapperFeature.DEFAULT_VIEW_INCLUSION
  • 禁用DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES

根据Jackson2ObjectMapperBuilder文档,如果类路径中存在某些模块,它还将注册一些模块:

  • jackson-datatype-jdk8:支持其他Java 8类型,例如Optional
  • jackson-datatype-jsr310:支持Java 8日期和时间API类型
  • jackson-datatype-joda:支持Joda-Time类型
  • jackson-module-kotlin:支持Kotlin类和数据类

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

4.3。 MappingJackson2HttpMessageConverter

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

@Bean

 public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {

 Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder().serializers(LOCAL_DATETIME_SERIALIZER)

 .serializationInclusion(JsonInclude.Include.NON_NULL);

 return new MappingJackson2HttpMessageConverter(builder.build());

 }

请务必查看我们的Spring Http Message Converters文章以了解更多信息。

5.测试配置

为了测试我们的配置,我们将使用TestRestTemplate并将对象序列化为String 。这样,我们可以验证我们的Coffee象是否已序列化,没有null值并且具有自定义日期格式:

@Test

 public void whenGetCoffee_thenSerializedWithDateAndNonNull() {

 String formattedDate = DateTimeFormatter.ofPattern(CoffeeConstants.dateTimeFormat).format(FIXED_DATE);

 String brand = "Lavazza";

 String url = "/coffee?brand=" + brand;



 String response = restTemplate.getForObject(url, String.class);



 assertThat(response).isEqualTo("{\"brand\":\"" + brand + "\",\"date\":\"" + formattedDate + "\"}");

 }

六,结论

在本教程中,我们研究了使用Spring Boot时配置JSON序列化选项的几种方法。

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

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *