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 객체를 반환 합니다.
- 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? 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 유형의 모든 빈을 자동으로 등록합니다 . 최종 결과는 다음과 같습니다.
{
"brand": "Lavazza",
"date": "16-11-2020 10:43"
}
3.2. Jackson2ObjectMapperBuilderCustomizer
이 기능적 인터페이스의 목적은 구성 빈을 생성 할 수 있도록하는 것입니다. Jackson2ObjectMapperBuilder 를 통해 생성 된 기본 ObjectMapper에 적용됩니다 .
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL)
.serializers(LOCAL_DATETIME_SERIALIZER);
}
구성 빈은 특정 순서로 적용되며 @Order 어노테이션을 사용하여 제어 할 수 있습니다 . 이 우아한 접근 방식은 다른 구성이나 모듈에서 ObjectMapper 를 구성하려는 경우에 적합 합니다.
4. 기본 구성 재정의
구성을 완전히 제어 하려면 자동 구성을 비활성화하고 사용자 지정 구성 만 적용 할 수있는 몇 가지 옵션이 있습니다 . 이러한 옵션을 자세히 살펴 보겠습니다.
4.1. ObjectMapper
기본 구성을 재정의하는 가장 간단한 방법은 ObjectMapper 빈 을 정의하고 @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 빈 을 정의하는 것 입니다. 실제로 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 : Optional 과 같은 다른 Java 8 유형 지원
- jackson-datatype-jsr310 : Java 8 날짜 및 시간 API 유형 지원
- jackson-datatype-joda : Joda-Time 유형 지원
- 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. 결론
이 예제에서는 Spring Boot를 사용할 때 JSON 직렬화 옵션을 구성하는 몇 가지 방법을 살펴 보았습니다.
기본 옵션을 구성하거나 기본 구성을 재정의하는 두 가지 접근 방식을 보았습니다.
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/spring-boot-customize-jackson-objectmapper
'Java' 카테고리의 다른 글
Redis 대 MongoDB (0) | 2021.04.21 |
---|---|
Spring에서 속성 파일 다시로드 (0) | 2021.04.20 |
Spring DispatcherServlet 소개 (0) | 2021.04.20 |
Spring MVC의 ViewResolver 사용방법(예제) (0) | 2021.04.20 |
Spring Handler 매핑 사용방법(예제) (0) | 2021.04.20 |