@JsonTypeInfo 활용 사례와 예제

2025. 3. 17. 11:19·개발중/Spring Boot
728x90
반응형

@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 애너테이션입니다.
  • 활용법:
    1. 상위 클래스나 인터페이스에 직접 적용하거나,
    2. Mixin을 사용하여 외부에서 적용할 수 있습니다.
  • 예제:
    위 예제에서는 Animal, Dog, Cat 클래스 계층을 통해 타입 정보를 JSON에 포함시키고, 역직렬화 시 올바른 하위 클래스로 복원하는 방법을 보여줍니다.

 

이와 같이 @JsonTypeInfo를 활용하면, 상속 관계에 있는 객체를 안전하게 JSON으로 직렬화/역직렬화할 수 있어 복잡한 도메인 모델을 다룰 때 매우 유용합니다.

728x90
반응형
저작자표시 (새창열림)

'개발중 > Spring Boot' 카테고리의 다른 글

package javax.xml.bind does not exist 해결  (0) 2024.12.11
Java: MAC Address 조회하기 예제  (0) 2024.12.10
Spring Cache 이해하고 사용하기: 성능 최적화를 위한 데이터 캐싱 도구  (0) 2024.11.19
ApplicationListener 를 이용해서 어플리케이션 기동시 에러날 경우에 대처하기.  (0) 2024.09.19
Mono와 Flux의 차이점과 활용법 - Spring WebFlux  (0) 2024.06.11
'개발중/Spring Boot' 카테고리의 다른 글
  • package javax.xml.bind does not exist 해결
  • Java: MAC Address 조회하기 예제
  • Spring Cache 이해하고 사용하기: 성능 최적화를 위한 데이터 캐싱 도구
  • ApplicationListener 를 이용해서 어플리케이션 기동시 에러날 경우에 대처하기.
Binsoo
Binsoo
내 트러블 슈팅
  • Binsoo
    정수빈 기술블로그임.
    Binsoo
  • 전체
    오늘
    어제
    • 빈수 개발자 개발 일기 (932) N
      • 개발중 (634) N
        • Spring Boot (95)
        • Spring Security (2)
        • Spring Batch (6)
        • Spring Boot & Redis (13)
        • Java Persistence API (JPA) (28)
        • Web (42)
        • Rest Api (7)
        • Spring Concurrency Control (3)
        • Redis (8)
        • Kubernetes (k8s) (4)
        • MYSQL (35)
        • AirFlow (15)
        • Docker (2)
        • Git (22)
        • Linux (9)
        • JSON Web Tokens (JWT) (4)
        • Troubleshooting (87)
        • Swagger (0)
        • Vue.js (52)
        • Java (74)
        • html (12)
        • C (5)
        • jQuery (15)
        • JavaServer Pages (JSP) (17)
        • Arduino (1)
        • JavaScript (35)
        • Amazon Web Services (AWS) (11)
        • Algorithm (9)
        • 참고 기능 (18) N
        • mongo (2)
      • PROJECT (27)
        • 스프링부트+JPA+몽고 API 개발 (3)
        • MINI (2)
        • 게시판 (3)
        • vue 프로젝트 (1)
        • JPA 사이드 프로젝트 기록 (17)
      • TEAM STUDY (156)
        • 가상 면접 사례로 배우는 대규모 시스템 설계 기초 (8)
        • 한 권으로 읽는 컴퓨터 구조와 프로그래밍 (12)
        • NAVER DEVELOPER (4)
        • LINUX (23)
        • PYTHON (19)
        • SERVER (8)
        • 알고리즘 코딩 테스트 스터디 (31)
        • 쿠버네티스 (40)
        • 대세는 쿠버네티스 [초급~중급] (11)
      • BOOK (0)
      • 자격증 (61)
        • 리눅스 1급 - 필기 기록 (19)
        • 네트워크 관리사 (2)
        • 네트워크 관리사 2급 - 실기 기록 (21)
        • 네트워크 관리사 2급 - 필기 기록 (16)
        • 정보처리 (2)
      • 직장인 대학원 (17)
        • 기록 (1)
        • 캐글 스터디 (3)
        • R (12)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    네트워크 관리사 2급 실기
    쿠버네티스
    Git 저장소
    springboot
    네트워크 관리사 자격증
    VUE
    jpa
    네트워크 관리사 요약
    BackendDevelopment
    리눅스 마스터 1급
    네트워크 관리사 2급
    파이썬 알고리즘
    리눅스 마스터 1급 요약
    java
    redis
    스프링
    파이썬
    쿠버네티스 스터디
    Spring
    네트워크 관리사 실기
    리눅스 마스터 요약
    네트워크 관리사 학점
    리눅스 마스터 1급 정리
    REST API
    리눅스 마스터
    리눅스 1급 요약
    git
    docker
    알고리즘
    네트워크 관리사
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
Binsoo
@JsonTypeInfo 활용 사례와 예제
상단으로

티스토리툴바