배경
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()
를 통해서 프로퍼티를 매핑한다.
- 일반적으로
@JsonCreator
는public
생성자가 하나 뿐인 경우에는 생략이 가능하다.
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>