jackson 활용해 JSON 변환시 추상 클래스 매핑하는 방법

2016-07-20 10:11

jackson 라이브러리를 활용해 자바 객체 => JSON, JSON 데이터 => 자바 객체로 변환한다. 이와 같이 변환을 할 때 상속 구조로 구현되어 있는 자바 객체를 JSON으로 변환하는데 문제가 발생한다.

예를 들어 다음과 같은 경우를 살펴보자. 회원 관리를 함에 있어 서비스 자체적으로 관리하는 회원과 Github과 같은 소셜 로그인을 통해 가입한 회원을 다음과 같이 상속 구조로 관리할 수 있다.

public abstract class User {
}

public class SrelloUser extends User {
}

public class GitHubUser extends User {
}

이와 같이 상속 구조로 객체를 관리하고 다른 객체에서 회원 객체와 의존관계를 가질 때 SrelloUser와 GitbhutUser와 같은 클래스로 의존관계를 가지는 것이 아니라 User로 의존관계를 가진다. 이 경우 jackson에서 JSON 데이터로 변환하거나 반대 작업을 하는 경우 에러가 발생한다.

jackson은 이 같은 문제점을 해결하기 위해 @JsonTypeInfo, @JsonSubTypes와 같은 애노테이션을 지원하고 있다. 이 애노테이션을 활용해 설정한 방법은 다음과 같다.

public enum UserType {
    SRELLO(Values.SRELLO), GITHUB(Values.GITHUB);

    private String type;

    private UserType(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }

    public static class Values {
        public static final String SRELLO = "S";
        public static final String GITHUB = "G";
    }
}
@JsonTypeInfo(
        use= JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type"
)
@JsonSubTypes({
    @Type(value = SrelloUser.class, name = UserType.Values.SRELLO),
    @Type(value = GitHubUser.class, name = UserType.Values.GITHUB),
})
public abstract class User {

}
@JsonTypeName(UserType.Values.SRELLO)
public class SrelloUser extends User {
}

@JsonTypeName(UserType.Values.GITHUB)
public class GitHubUser extends User {
}

위와 같이 설정한 후 다음과 같이 테스트 코드를 만들어 실행한 결과 다음과 같은 JSON 데이터를 얻을 수 있다.

public class UserJsonMappingTest {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserJsonMappingTest.class);

    @Test
    public void mixin() throws Exception {
        User srelloUser = new SrelloUser("userId", "javajigi@slipp.net", "password");
        ObjectMapper mapper = new ObjectMapper();
        LOGGER.debug("result : {}", mapper.writeValueAsString(srelloUser));
    }
}
{"type":"S","id":0,"userId":"userId","email":"javajigi@slipp.net","password":"password","guestUser":false}

이에 대한 해결 방법을 찾기 위해 jackson의 mixin을 사용하는 예제들이 많았는데 굳이 그럴 필요없이 자바 객체에 위와 같이 설정한 것만으로도 충분히 잘 동작했다.

0개의 의견 from SLiPP

의견 추가하기