Java에서 JSON 문자열을 ObjectMapper
를 사용해 자바 객체로 변환할 때, 특히 List
나 Map
같은 제네릭 타입을 다룰 때 TypeReference
는 꼭 필요한 도구입니다. 이 글에서는 TypeReference
가 왜 필요한지, 이를 사용할 때 얻는 이점, 그리고 TypeReference
를 활용한 예제를 통해 그 활용법을 알아보겠습니다.
TypeReference
가 필요한 이유Java에서는 제네릭 타입 정보가 컴파일 시점에 소거(Type Erasure)되므로, 런타임에서는 제네릭 타입에 대한 구체적인 정보를 알 수 없습니다. ObjectMapper
는 JSON 데이터를 자바 객체로 매핑하는 과정에서 타입 정보를 기반으로 각 필드를 적절한 타입으로 변환합니다. 하지만 다음과 같은 경우 문제가 발생할 수 있습니다:
String json = "[{\"name\":\"Alice\", \"age\":30}, {\"name\":\"Bob\", \"age\":25}]";
List<Person> personList = objectMapper.readValue(json, List.class);
위 코드에서는 List<Person>
로 변환하고자 했지만, ObjectMapper
는 타입 정보를 충분히 알 수 없어 List
의 원소를 LinkedHashMap
으로 반환하게 됩니다. 이로 인해 Person
클래스의 필드에 접근하거나 관련 메서드를 호출하는 것이 불가능해집니다.
이럴 때 TypeReference
를 사용하면 제네릭 타입 정보를 포함한 변환이 가능합니다.
TypeReference
사용 예제아래의 예제에서는 ObjectMapper
와 TypeReference
를 사용해 JSON 데이터를 List<Person>
으로 정확하게 변환해 보겠습니다.
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
class Person {
private String name;
private int age;
// Getters, Setters, toString()
}
public class TypeReferenceExample {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
// JSON 문자열
String json = "[{\"name\":\"Alice\", \"age\":30}, {\"name\":\"Bob\", \"age\":25}]";
// TypeReference를 사용하여 JSON을 List<Person>으로 변환
List<Person> personList = objectMapper.readValue(json, new TypeReference<List<Person>>() {});
System.out.println("personList = " + personList);
}
}
personList = [Person{name='Alice', age=30}, Person{name='Bob', age=25}]
위 예제에서 TypeReference<List<Person>>
을 사용하여 JSON 문자열을 List<Person>
타입으로 변환했습니다. TypeReference
가 없으면 ObjectMapper
는 List
타입으로만 인식하게 되어 Person
객체로 변환하지 못합니다.
TypeReference
의 장점TypeReference
는 제네릭 타입 정보를 유지해 주므로, 원하는 구체 타입으로 정확히 매핑할 수 있습니다.TypeReference
를 통해 원하는 타입을 명확히 지정하므로 코드의 가독성이 높아집니다.TypeReference
와 다른 활용 예Map<String, List<Person>>
타입으로 변환하기TypeReference
는 중첩된 제네릭 타입도 변환할 수 있습니다. 예를 들어, JSON 데이터를 Map<String, List<Person>>
으로 변환하는 경우입니다.
String json = "{\"teamA\":[{\"name\":\"Alice\",\"age\":30}], \"teamB\":[{\"name\":\"Bob\",\"age\":25}]}";
Map<String, List<Person>> teams = objectMapper.readValue(json, new TypeReference<Map<String, List<Person>>>() {});
System.out.println("teams = " + teams);
이 예제에서도 TypeReference
를 사용하여 JSON 데이터를 중첩된 제네릭 타입 Map<String, List<Person>>
으로 정확히 변환할 수 있습니다.
TypeReference
사용 시 주의사항TypeReference
는 추상 클래스로, 인스턴스화할 때 항상 익명 클래스로 선언해야 합니다.TypeReference
사용 시, ObjectMapper
는 타입 분석을 위한 추가적인 처리가 필요할 수 있어 약간의 성능 비용이 있을 수 있습니다. 그러나 이는 제네릭 타입 변환의 정확성에 비해 미미한 비용입니다.TypeReference
는 JSON 데이터를 복잡한 제네릭 타입으로 변환할 때 매우 유용합니다. 이를 통해 구체적인 타입을 정확히 지정할 수 있으며, 코드의 가독성과 안정성 또한 높일 수 있습니다.