[Java] jackson 라이브러리는 왜 non-static Inner class를 매핑하지 못할까?
프런트와 http로 통신할 때 JSON 형식으로 데이터를 받는 경우가 많습니다. 객체지향언어인 Java에서 객체로 바인딩 하는 문제를 도와주는 라이브러리 중 하나인 jackson
은 대표적인 ObjectMapper
클래스를 제공합니다.
ObjectMapper 클래스는 JSON을 읽기, 쓰기 기능 뿐만아니라 JSON Tree Model인 JsonNode 형태 가공해주기도 합니다.
기본적인 jackson 라이브러리에 대한 설명은 마치고, 다룰 주제인 non-static Inner class인 경우
convertValue(Object fromValue, Class<T> toValue)
메서드에서 왜 com.fasterxml.jackson.databind.exc.InvalidDefinitionException
를 날리는지 알아보겠습니다.
Inner class? static?
jackson 외에 Hibernate 프레임워크에서도 non-static Inner class
의 경우 데이터 바인딩을 해주지 못합니다.
Java Inner Class엔 3가지 종류가 있습니다. Anonymous, non-static, static 입니다. Anonymous는 익명 내부 클래스이며 하나의 인터페이스나 추상 클래스를 구현하는 용도로만 쓰입니다.
non-static과 static inner class는 동일한 하나의 copy가 쓰이는 정적이란(static) 외에도 차이가 있습니다. 바로 non-static inner class는 보이지 않는 변수(hidden variable)들이 생성자(hidden)를 통해 컴파일러가 추가한다는 것입니다.
그 결과로 사실상 final 전역변수가 있기 때문에 기본 생성자가 없는 상태에 놓이게 됩니다.
public class Period {
class Monthly {
public int getMonths() {
return 1;
};
}
}
위와 같은 코드가 있다면, 컴파일러는 아래와 같이 생성해주게 됩니다.
public class Period { ... }
class Period$Monthly {
private final Period parent;
Period$Monthly(Period p) {
parent = p;
}
public int getMonths() {
return 1;
};
}
왜냐하면 이렇게 될 경우 inner class인 Monthly 클래스가 외부 클래스인 Period 클래스의 모든 변수들(private 일지라도)에 대해 접근할 수 있는 권한을 가지기 때문입니다.
이와 달리 static inner class
는 컴파일링 시 숨겨진 variable이나 생성자가 없습니다.
결국 jackson 라이브러리가 non-static inner class에 대해 exception을 던지는 이유는, 기본 생성자가 없어 객체를 초기화 시키지 못하기 때문입니다.(instantiate class) 따라서 inner 클래스를 JSON 매핑해줄 경우 static을 명시해야함을 알 수 있습니다.
참고자료