본문 바로가기

Programming/Java & Spring 관련 내용 정리

[Java] 역직렬화로 JSON 포맷을 바꿔보았다.

백오피스 프로젝트를 개발하던 중에  Jackson 라이브러리를 통해  '역직렬화'를 사용해 보았다.

 

 

먼저 상황은 다음과 같았다.

 

프로모션 관련 백오피스 기능이었는데,

프로모션을 등록할 때 섹션 종류가 총 3가지가 있었다. (buttion, image, detail)

 

이 때 프론트에서 세팅해야하는 JSON 데이터 포맷을

맨 처음에는 아래 이미지에서 A와 같이 되도록 코드를 작성했었다.

 

 

 

 

 

sectionType이 달라짐에 따라

"imageSection" , "buttonSection", "detailSection" 과 같은 필드가 따로 따로 생기는 방식이었다.

 

프론트 입장을 고려했을 때는 

A 보다는 B 방식이 데이터를 다루는 데 있어서 더 편하다고 판단하였고

B 와 같이 JSON 포맷이 되도록 하기 위해 Jackson의 역직렬화 어노테이션을 이용해서 코드를 작성해보았다.

 

 

전체적인 코드 틀은 다음과 같다. (세세한 필드는 생략)

 

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXISTING_PROPERTY,
        visible = true,
        property = "sectionType")
@JsonSubTypes(value = {
        @JsonSubTypes.Type(value = ImageSection.class, name = "image"),
        @JsonSubTypes.Type(value = ButtonSection.class, name = "button"),
        @JsonSubTypes.Type(value = DetailSection.class, name = "detail"),
})
@Data
public class PromotionSection {
    
    @Schema(description = "섹션 타입", example = "image / button / detail")
    private PromotionSectionType sectionType;


    @Getter
    @Setter
    public static class ImageSection extends PromotionSection {
        // ...생략
    }


    @Getter
    @Setter
    public static class ButtonSection extends PromotionSection {
        // ...생략
    }

    @Getter
    @Setter
    public static class DetailSection extends PromotionSection {
        // ...생략
    }

 

 

이렇게 되면 JSON 요청 데이터에서 
"sectionType" 이라는 필드의 값이 "image"면 ImageSection을 DTO로 인식하게 된다. 

 

 

 

Jackson 라이브러리는 @JsonTypeInfo와 @JsonSubTypes 어노테이션 설정을 통해

JSON 데이터 내에 있는 특정 필드의 값을 기준으로 객체의 타입을 인식하고 매핑하기 때문이다.

 

 


 

사용됐던

@JsonTypeInfo 어노테이션과 @JsonSubTypes 어노테이션을

아래와 같이 조금 더 자세히 살펴보고자 한다.

 

 

 

 

  • use = JsonTypeInfo.Id.NAME
    • Id Enum Value는 직렬화 중에 식별자를 어떤 것으로 할 지 정의하는 value 이다.
    • 구현 클래스마다 이름이 달라서 여기서는 NAME으로 설정해 주었다.
    • use 부분은 어노테이션이 위치한 클래스의 유형 및 하위 유형의 인스턴스에 대한 정보를 직렬화, 역직렬화 할때 지정해야하는 프로퍼티이다.
    • 정리하면 "직렬화 할 때 클래스 명으로 식별하겠다" 라는 의미이다.

 

  • include = JsonTypeInfo.As.EXISTING_PROPERTY
    • 다형성 정보를 JSON 데이터에 추가하는 방식 중 하나이다.
    • EXISTING_PROPERTY를 사용하면 JSON 데이터를 자바 객체로 변환하거나 자바 객체를 JSON 데이터로 변환할 때, getter와 setter 메서드를 사용할 수 있게 된다.
    • 이를 통해 좀 더 간단하고 편리한 역직렬화 및 직렬화를 할 수 있다.

 

  • visible = true
    • 설정을 true로 하면, 다형성 정보가 JSON 데이터에 포함되어 해당 객체의 타입을 식별하는 프로퍼티의 값이 표시된다.
    • 따로 설정하지 않으면 해당 정보는 JSON 데이터에 포함되지 않게 된다.

 

  • property = "sectionType"
    • JSON 데이터 내에서 어떤 프로퍼티를 사용하여 객체의 다형성 정보를 식별할 것인지를 나타낸다.
    • 이를 통해 Jackson은 해당 프로퍼티를 기반으로 객체의 타입을 식별하고, 그에 맞게 역직렬화를 수행한다.

 

  • @JsonSubTypes.Type(name = "XXX", value = XXX.class)
    •  JSON 데이터에서 사용되는 논리적 이름과 직렬화 가능한 하위 클래스의 유형을 연결하기 위해 @JsonTypeInfo와 함께 사용되는 주석이다.
    • Type 요소는 JSON 데이터에 사용되는 논리적인 이름과 각 하위 클래스의 실제 클래스를 연결한다.
    • value
      • 직렬화 가능한 하위 클래스의 실제 자바 클래스를 지정한다.
      • JSON 데이터에서 해당 클래스가 식별될 때 이 클래스로 역직렬화된다.
    • name
      • JSON 데이터에서 사용되는 논리적 이름을 지정한다.
      • JSON 데이터에 나타날 식별자 역할을 하며, 이 값은 JsonTypeInfo에서 설정한 property에 해당한다.