Рубрики
Без рубрики

Весенняя загрузка: Настройка объекта Jackson ObjectMapper

Узнайте, как настроить параметры сериализации и десериализации для Джексона с помощью Spring Boot.

Автор оригинала: baeldung.

1. Обзор

При использовании формата JSON Spring Boot будет использовать экземпляр ObjectMapper для сериализации ответов и десериализации запросов. В этом руководстве мы рассмотрим наиболее распространенные способы настройки параметров сериализации и десериализации.

Чтобы узнать больше о Джексоне, обязательно ознакомьтесь с нашим учебником по Джексону .

2. Конфигурация по умолчанию

По умолчанию конфигурация весенней загрузки будет:

  • Отключить MapperFeature.DEFAULT_VIEW_INCLUSION
  • Отключите DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
  • Отключите SerializationFeature.WRITE_DATES_AS_TIMESTAMPS

Давайте начнем с краткого примера:

  • Клиент отправит запрос GET на наш /coffee?name=Lavazza
  • Контроллер вернет новый Кофе объект
  • Spring будет использовать ObjectMapper для сериализации нашего POJO в JSON

Мы проиллюстрируем параметры настройки с помощью String и LocalDateTime объектов:

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?бренд=Lavazza будет:

{
  "name": null,
  "brand": "Lavazza",
  "date": "2020-11-16T10:21:35.974"
}

Мы хотели бы исключить значения null и иметь пользовательский формат даты (дд-ММ-гггг ЧЧ:мм). Окончательный ответ будет следующим:

{
  "brand": "Lavazza",
  "date": "04-11-2020 10:34"
}

При использовании Spring Boot у нас есть возможность настроить ObjectMapper по умолчанию или переопределить его. Мы рассмотрим оба этих варианта в следующих разделах.

3. Настройка ObjectMapper по умолчанию

В этом разделе мы рассмотрим, как настроить по умолчанию ObjectMapper , который использует Spring Boot.

3.1. Свойства приложения и Пользовательский модуль Джексона

Самый простой способ настройки картографа-через свойства приложения . Общая структура конфигурации такова:

spring.jackson..=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.Модуль. Конечный результат будет:

{
  "brand": "Lavazza",
  "date": "16-11-2020 10:43"
}

3.2. Настройщик Jackson2ObjectMapperBuilder

Цель этого функционального интерфейса состоит в том, чтобы позволить нам создавать компоненты конфигурации. Они будут применены к объекту по умолчанию ObjectMapper , созданному с помощью Jackson2ObjectMapperBuilder :

@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
    return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL)
      .serializers(LOCAL_DATETIME_SERIALIZER);
}

Компоненты конфигурации применяются в определенном порядке, которым мы можем управлять с помощью @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 documentation , он также зарегистрирует некоторые модули, если они присутствуют в пути к классам:

  • jackson-datatype-jdk8: поддержка других типов Java 8, таких как Необязательно
  • jackson-datatype-jsr310: поддержка типов API даты и времени Java 8
  • jackson-datatype-joda: поддержка типов времени Joda
  • jackson-module-kotlin: поддержка классов Kotlin и классов данных

Преимущество этого подхода заключается в том, что Jackson2ObjectMapperBuilder предлагает простой и интуитивно понятный способ создания ObjectMapper .

4.3. MappingJackson2HttpMessageConverter

Мы можем просто определить боб с типом MappingJackson2HttpMessageConverter , и 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 + "\"}");
}

6. Заключение

В этом руководстве мы рассмотрели несколько методов настройки параметров сериализации JSON при использовании Spring Boot.

Мы видели два разных подхода: настройка параметров по умолчанию или переопределение конфигурации по умолчанию.

Как всегда, полный исходный код статьи доступен на GitHub .