이번 포스팅에서는 JsonDeserializer를 사용하는 방법에 대해 알아보도록 하겠습니다.
JsonDeserializer는 Jackson 라이브러리에서 제공하는 클래스입니다.
주로 JSON 데이터를 Java 객체로 변환하는 과정에서 기본 매핑 방식으로 처리할 수 없는 경우, 사용자 정의 변환 로직을 작성할 수 있도록 제공합니다.
프로젝트에서 주로 사용하는 스프링 부트는 HttpMessageConverter
로 Jackson의 MappingJackson2HttpMessageConverter
를 자동 등록합니다.
이 설정은 JSON 데이터를 요청 바디(@RequestBody
)나 응답(@ResponseBody
)로 처리할 때 사용됩니다.
그렇기 때문에 스프링 부트 프로젝트에서는 별다른 의존성 주입 없이 어노테이션을 통해서 JSON 데이터를 원하는 DTO로 변환하여 사용이 가능합니다.
예를 들어, List 또는 Map 같은 기본적인 자료구조의 경우 배열 형태 또는 key, value 형태의 JSON 데이터를 해당 자료구조에 알맞게 자동 변환을 해줍니다.
이와 같이 Jackson은 기본적으로 JSON 데이터와 Java 객체 간의 직렬화/역직렬화를 처리하지만, 특정한 데이터 구조나 변환 규칙이 필요한 경우에는 JsonDeserializer를 사용해 사용자 정의 역직렬화 로직을 구현할 수 있습니다.
JsonDeserializer 사용법에 대해서 알아보도록 하겠습니다. 아래의 예시에서는 Map 타입 필드를 사용하고 있는데 원래 Jackson 라이브러리가 자동으로 변환해줍니다. 간단한 사용법 예시이니 참고해주시면 좋을 것 같습니다.
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.Map;
public class StringToMapDeserializer extends JsonDeserializer<Map> {
@Override
public Map deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(jsonParser.getText(), new TypeReference<Map>() {
});
}
}
먼저 StringToMapDeserializer
클래스가 JsonDeserializer<Map>
를 상속하여 특정 필드에 대해 JSON 데이터의 사용자 정의 변환 로직을 제공하도록 만듭니다.
ObjectMapper
는 Jackson 라이브러리의 핵심 클래스로, JSON 문자열을 Java 객체로 변환합니다. ObjectMapper
의 readValue
메서드의 첫 번째 파라미터에는 JSON 데이터를 문자열로 가져오는 JsonParser.getText()
를 호출해줍니다.
두 번째 파라미터에 TypeReference<Map>
제네릭 타입을 명시하여 Map(CustomClass
)으로 변환되도록 지정해줍니다.
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Setter
public class ReservationRegisterRequestDto {
...
>> @JsonDeserialize(using = StringToMapDeserializer.class)
private Map<Long, Integer> options;
>> @JsonDeserialize(using = StringToMapDeserializer.class)
private Map<String, Object> guest;
...
}
위에서 작성한 StringToMapDeserializer
클래스를 통해 역직렬화할 대상의 속성에 @JsonDeserializer(using = StringToMapDeserializer.class)
형태의 어노테이션을 추가해주면 됩니다.
이 필드들은 요청 JSON의 문자열 형태를 받아 Jackson의 사용자 정의 역직렬화 로직으로 처리됩니다.