네이티브와 API 통신 시, json으로 response를 내려줄 때 null인 value를 blank("")로 치환해달라는 요청사항이 들어왔다.
전지전능하신 SpringBoot과 Jackson 라이브러리는 수 많은 개발자들의 요구사항을 프로퍼티 설정이나, 애노테이션 하나로 해결해주셨기에, 흔쾌히 '네 알겠습니다.' 를 시전했지만, 그 어떤 프로퍼티도 어떤 Jackson 애노테이션도 나를 구원해주진 않으셨다.
그러나 모름지기 개발자라면 없는 기능도 만들어내야 하는 법(사실 있는 기능에 숟가락만 얹었다.)
해결과정을 서술해 나가겠다.(숟가락 얹는 방법을 서술하겠다.)
일단 이런 요구 사항에 대해 2가지 유형이 있다.
- 전체 프로젝트에서 null -> blank 적용
- 일부 거래에서만 null-> blank 적용
비교적 손이 덜 가는 전체 프로젝트에서 null -> blank 적용 방법을 먼저 서술하겠다.
우선 구글링을 해보니 아래와 같은 좋은 글이 있었다.
Json 응답시 Null값을 ""으로 자동으로 바꾸기.
Spring에서 RestController를 이용해서 Json으로 응답을 주고 있는데, 모든 API에 대해서 Null값은 "" 으로 바꿔줘야 했다. 응닶값이 Null이면 제거해 주는 Annotation은 존재하지만 공백으로 바꿔주는 Annotation
hspmuse.tistory.com
요약하면,
1. JsonSerializer를 상속받아 null을 ""로 치환하는 클래스를 만들고
2. ObjectMapper를 상속받은 CustomObjectMapper에 json 프로퍼티의 값이 null일 때 1.에서 만든 객체가 수행되도록 붙이고
3. MappingJackson2HttpMessageConverter 객체에 2. 에서 만든 CustomObjectMapper를 붙이고 이를 Bean으로 등록해 사용한다.
이대로만 하더라도 기능은 구현된다. 그러나 약간의 아쉬운 점이 존재했다.
바로 SpringBoot AutoConfiguration으로 설정된 ObjectMapper의 설정이 하나도 적용이 안된다는 것이다.
기본 ObjectMapper를 그냥 상속받아 SerializerProvider만 달랑 설정해주니 당연한 노릇이다.
Request로 들어올 때, LocalDate은 어떤 형식으로 받을 것이며... timezone은 어떤 형식으로 받을 것이며.... DTO에 없는 필드로 값이 들어올 때는 ignore를 할 것인지 등...
SpringBoot의 ObjectMapper 관련하여 어떤 설정을 잡아주는 확인하고 싶다면, Jackson2ObjectMapperBuilder#configure를 참조하십시오
그러면 위 블로그에서 제시된 방법을 조금만 응용하면 되겠는데? 싶었다.
- ObjectMapper는 SpringBoot가 친절히 설정하여 Bean으로 등록한 것을 가져와서,
- NullValueSerializer만 JsonSerializer를 상속받아 null을 blank로 치환하는 역할을 가지고 있는 객체로 set하고,
- 그렇게 만든 ObjectMapper를 MappingJackson2HttpMessageConverter 생성자로 넘겨 객체를 생성하고 Bean으로 등록
아래 두 코드블록만 복붙하면, SpringBoot가 ObjectMapper에 설정한 것은 그대로 유지하면서도, 편리하게 null -> blank 치환이 가능할 것이다.
public class NullToEmptyStringSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString("");
}
}
@Configuration
public class JsonCustomConfig {
@Bean
public MappingJackson2HttpMessageConverter httpMessageConverter(ObjectMapper objectMapper){
objectMapper.getSerializerProvider()
.setNullValueSerializer(new NullToEmptyStringSerializer());
MappingJackson2HttpMessageConverter httpMessageConverter
= new MappingJackson2HttpMessageConverter(objectMapper);
return httpMessageConverter;
}
}
참 별것 아니고, 별로 기술할 것도 없지만, 정확하게 기능을 확장하기 위해서는 SpringBoot AutoConfiguration을 분석해봐야 한다.
끝
다음 포스트는 일부 거래에 대해 null->blank 치환하는 방법에 대해 서술하겠다.