@JsonTypeInfo란?
@JsonTypeInfo는 Jackson 라이브러리에서 다형성(Polymorphism) 직렬화와 역직렬화를 지원하기 위해 사용되는 애너테이션입니다.
객체지향 프로그래밍에서 상속 구조를 가지는 클래스 계층이 있을 때, 상위 클래스 타입으로 선언된 필드에 여러 하위 클래스의 객체가 저장될 수 있습니다.
이러한 상황에서 객체를 JSON으로 직렬화할 때, 단순히 필드 값만 기록하면 역직렬화 시 원래의 구체적인 클래스 정보를 알 수 없습니다.
@JsonTypeInfo는 이 문제를 해결하기 위해, JSON 데이터에 타입 정보를 포함시켜 저장함으로써, 역직렬화 시 원래의 하위 클래스로 복원할 수 있도록 도와줍니다.
주요 속성은 다음과 같습니다:
- use: 타입 식별자(strategy)를 지정합니다.
예를 들어, JsonTypeInfo.Id.CLASS를 사용하면, 클래스의 FQCN(전패키지 이름 포함 클래스명)이 타입 식별자로 사용됩니다. - include: 타입 정보를 JSON의 어디에 포함시킬지 결정합니다.
예: JsonTypeInfo.As.PROPERTY는 JSON 객체의 프로퍼티로 포함시킵니다. - property: 타입 정보를 저장할 프로퍼티 이름을 지정합니다.
예를 들어, "@class"로 지정하면, JSON에 "@class": "com.example.MySubClass" 형태로 저장됩니다.
@JsonTypeInfo 활용법
@JsonTypeInfo를 활용하면, 상속 구조를 가진 객체들을 직렬화할 때 자동으로 타입 정보를 포함할 수 있습니다.
일반적인 활용 방법은 두 가지입니다
기본 클래스에 직접 적용하기
상위 클래스나 인터페이스에 @JsonTypeInfo를 직접 적용하여, 하위 클래스들을 직렬화할 때 타입 정보가 포함되도록 할 수 있습니다.
예제에서는 Animal 클래스에 타입 정보를 포함시키도록 지정했으므로, 하위 클래스의 인스턴스를 직렬화하면 JSON에 "@class" 필드가 추가됩니다.
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(
use = JsonTypeInfo.Id.CLASS,
include = JsonTypeInfo.As.PROPERTY,
property = "@class"
)
public abstract class Animal {
private String name;
// getters, setters, etc.
}
Mixin을 사용하여 적용하기
만약 기존의 클래스에 직접 애너테이션을 추가하기 어려운 경우, Jackson의 Mixin 기능을 활용하여 외부에서 애너테이션을 적용할 수 있습니다.
이렇게 하면, Animal 클래스에 직접 애너테이션을 붙이지 않아도, Mixin을 통해 타입 정보가 포함된 JSON 직렬화/역직렬화가 가능해집니다.
// Mixin 클래스 (실제 로직은 없고 애너테이션만 포함)
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(
use = JsonTypeInfo.Id.CLASS,
include = JsonTypeInfo.As.PROPERTY,
property = "@class"
)
public abstract class AnimalMixin {}
// ObjectMapper 설정 시 Mixin을 등록
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Animal.class, AnimalMixin.class);
@JsonTypeInfo 예제
1. 상속 구조가 있는 클래스 예제
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@JsonTypeInfo(
use = JsonTypeInfo.Id.CLASS,
include = JsonTypeInfo.As.PROPERTY,
property = "@class"
)
abstract class Animal {
public String name;
}
class Dog extends Animal {
public double barkVolume;
public Dog() {} // 기본 생성자 필수
public Dog(String name, double barkVolume) {
this.name = name;
this.barkVolume = barkVolume;
}
}
class Cat extends Animal {
public int lives;
public Cat() {}
public Cat(String name, int lives) {
this.name = name;
this.lives = lives;
}
}
public class JsonTypeInfoExample {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
Animal dog = new Dog("Buddy", 10.5);
String dogJson = mapper.writeValueAsString(dog);
System.out.println("Serialized Dog:\n" + dogJson);
// 역직렬화 시 원래 클래스 타입으로 복원
Animal deserializedDog = mapper.readValue(dogJson, Animal.class);
System.out.println("Deserialized Dog Class: " + deserializedDog.getClass().getName());
}
}
2. Mixin 활용 예제
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
abstract class Animal {
public String name;
}
class Dog extends Animal {
public double barkVolume;
public Dog() {}
public Dog(String name, double barkVolume) {
this.name = name;
this.barkVolume = barkVolume;
}
}
// Mixin 정의
@JsonTypeInfo(
use = JsonTypeInfo.Id.CLASS,
include = JsonTypeInfo.As.PROPERTY,
property = "@class"
)
abstract class AnimalMixin {}
public class MixinExample {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Animal.class, AnimalMixin.class);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
Animal dog = new Dog("Buddy", 10.5);
String json = mapper.writeValueAsString(dog);
System.out.println("Serialized with Mixin:\n" + json);
Animal deserializedDog = mapper.readValue(json, Animal.class);
System.out.println("Deserialized Dog Class: " + deserializedDog.getClass().getName());
}
}
결론
- @JsonTypeInfo란?
다형성 직렬화/역직렬화를 지원하기 위해 JSON에 타입 정보를 포함시키는 Jackson 애너테이션입니다. - 활용법:
- 상위 클래스나 인터페이스에 직접 적용하거나,
- Mixin을 사용하여 외부에서 적용할 수 있습니다.
- 예제:
위 예제에서는 Animal, Dog, Cat 클래스 계층을 통해 타입 정보를 JSON에 포함시키고, 역직렬화 시 올바른 하위 클래스로 복원하는 방법을 보여줍니다.
이와 같이 @JsonTypeInfo를 활용하면, 상속 관계에 있는 객체를 안전하게 JSON으로 직렬화/역직렬화할 수 있어 복잡한 도메인 모델을 다룰 때 매우 유용합니다.
'개발중 > Spring' 카테고리의 다른 글
package javax.xml.bind does not exist 해결 (0) | 2024.12.11 |
---|---|
Java: MAC Address 조회하기 예제 (0) | 2024.12.10 |
Spring Cache 이해하고 사용하기: 성능 최적화를 위한 데이터 캐싱 도구 (0) | 2024.11.19 |
Spring Project 의 MyBatis 쿼리를 Console 에 찍는 설정 (log4j2) (1) | 2023.12.30 |
Spring 환경에서 프로파일 별 효율적 코드 관리 전략 (1) | 2023.12.08 |
댓글