배경

data class Person(var id: Long? = null, var name: String? = null)

fun main() {  
   val objectMapper = ObjectMapper()  
   val person: Person = objectMapper.readValue("{\"id\":1, \"name\": \"junroot\"}", Person::class.java)  
   println(person.name)  
}
  • ObjectMapper를 통해 역직렬화하는 경우, 기본 생성자를 이용해 객체를 생성한 뒤 자바 리플렉션을 이용해 값을 주입하고 있다.

  • 따라서 기본 생성자가 필요한데 이렇게 되면 프로퍼티들이 불변일 수가 없게된다.

  • @JsonCreator@JsonProperty를 통해서 생성 가능하다는 사실을 알게되고 이를 사용했었다.

data class Person @JsonCreator constructor(  
   @JsonProperty("id")  
   val id: Long,  
   @JsonProperty("name")  
   val name: String  
)  
  
fun main() {  
   val objectMapper = ObjectMapper()  
   val person: Person = objectMapper.readValue("{\"id\":1, \"name\": \"junroot\"}", Person::class.java)  
   println(person.name)  
}
  • 코드 리뷰로 @JsonCreator 가 없어도 정상적으로 동작한다고 받았다. 역직렬화 과정에 어떻게 객체를 생성하고 필드에 값을 주입하는지 과정을 정리해보고자 한다.
data class Person (  
   @JsonProperty("id")  
   val id: Long,  
   @JsonProperty("name")  
   val name: String  
)  
  
fun main() {  
   val objectMapper = ObjectMapper()  
   val person: Person = objectMapper.readValue("{\"id\":1, \"name\": \"junroot\"}", Person::class.java)  
   println(person.name)  
}

@JsonCreator

  • 내가 정의한 생성자로 역직렬화하기 위해서는 @JsonCreator를 사용해야된다.
  • @JsonCreator에는 대표적으로 2가지 모드가 있다.
    • DELEGATING: 인자가 하나인 경우에만 사용할 수 있다. json 데이터 값 전체를 인자로 바인딩 한다.
    • PROPERTIES: 인자가 여러개인 경우 사용한다. 생성자 인자에 있는 객체와 매칭되는 프로퍼티의 이름과 바인딩한다.
      • 일반적으로 @JsonProperty()를 통해서 프로퍼티를 매핑한다.
  • @JsonCreatorpublic 생성자가 하나 뿐인 경우에는 생략이 가능하다.

Parameter Names Module

  • Jackson 2.x, Java 8 이상부터는 생성자의 파라미터 이름을 읽어서 프로퍼티 이름으로 사용하는 모듈이 추가되었다. 이를 사용하면 @JsonCreator를 사용할 때, @JsonProperty가 생략 가능하다.

  • maven 의존성 추가

<dependency>  
   <groupId>com.fasterxml.jackson.module</groupId>  
   <artifactId>jackson-module-parameter-names</artifactId>  
   <version>2.15.0</version>  
</dependency>
  • module 등록
objectMapper.registerModule(new ParameterNamesModule());
  • Kotlin을 사용할경우 ParameterNamesModule 등록해도 동작하지 않을 수 있다. kotlinModule을 등록해주면 동작한다.
    • maven 의존성 추가
<dependency>  
   <groupId>com.fasterxml.jackson.module</groupId>  
   <artifactId>jackson-module-kotlin</artifactId>  
   <version>2.14.2</version>  
</dependency>

참고 자료