이번 포스팅에선 Jackson의 @JsonValue 사용법에 대해 알아보겠다.
프로젝트에서 제일 많이 사용하는 jackson 어노테이션인데 아무 생각없이 쓰다가 문득 정리하고 싶어서 정리한다.
@JsonValue란?
@JsonValue는 직렬화할 때 사용하는 어노테이션으로 클래스의 프로퍼티, getter, 인자가 없는 메소드 에 사용할 수 있으며, 최대 1개만 사용이 가능하다. (2개 이상 사용하면 "Multiple 'as-value' properties defined" 에러가 발생한다.)
특이한 건 enum에 사용하면 직렬화, 역직렬화 둘 다에 사용된다. 단, @JsonCreator가 있는 경우 @JsonValue는 역직렬화에 사용되지 않는다.
@JsonValue 사용법
Class + @JsonValue
프로퍼티, getter, 인자가 없는 메소드 이렇게 3군데에 붙일 수 있다.
Member에 @JsonValue를 선언 후 MemberResponse를 직렬화하는 방식으로 테스트를 진행했다.
class MemberResponse(
val member: Member
)
class Member(
val id: Long,
val name: String
)
프로퍼티
프로퍼티 위에 @JsonValue를 선언해주면 된다.
class Member(
val id: Long,
@JsonValue
val name: String,
)
Member가 직렬화될 때 @JsonValue가 선언된 name의 값을 사용한다.
@Test
fun testJsonValueOnProperty() {
val objectMapper = ObjectMapper().registerKotlinModule()
val response = MemberResponse(Member(1, "노력남자"))
assertEquals("""{"member":"노력남자"}""".trimIndent(), objectMapper.writeValueAsString(response))
}
게터
프로퍼티 위에 @get:JsonValue를 선언해주면 된다.
class Member(
val id: Long,
@get:JsonValue
val name: String
)
Member가 직렬화될 때 @JsonValue가 선언된 name의 게터를 사용한다.
@Test
fun testJsonValueOnGetter() {
val objectMapper = ObjectMapper().registerKotlinModule()
val response = MemberResponse(Member(1, "노력남자"))
assertEquals("""{"member":"노력남자"}""".trimIndent(), objectMapper.writeValueAsString(response))
}
인자가 없는 메소드
인자가 없는 메소드에 @JsonValue를 붙여주면 된다. (인자가 있는 메소드에 @JsonValue를 붙이면 인식이 안 된다.)
대게 toString에 @JsonValue를 붙여서 사용한다.
class Member(
val id: Long,
val name: String
) {
@JsonValue
override fun toString(): String {
return "$id-$name"
}
}
Member가 직렬화될 때 @JsonValue가 선언된 toString()을 사용한다.
@Test
fun testJsonValueOnToString() {
val objectMapper = ObjectMapper().registerKotlinModule()
val response = MemberResponse(Member(1, "노력남자"))
assertEquals("""{"member":"1-노력남자"}""".trimIndent(), objectMapper.writeValueAsString(response))
}
enum + @JsonValue
enum도 마찬가지로 프로퍼티, getter, 인자가 없는 메소드에 붙일 수 있다.
class에 사용하는 거랑 동일한 부분은 테스트하지 않겠다.
class랑 다른 건 enum에 선언된 @JsonValue는 직렬화, 역직렬화에 모두 사용된다는 점이다.
(단, @JsonCreator가 있는 경우 역직렬화에 사용되지 않음)
아래 User를 역직렬화해서 잘 동작하는지 테스트해보겠다.
class User(
val userType: UserType
) {
enum class UserType(
@JsonValue val code: Int
) {
NORMAL(0),
ADMIN(1);
}
}
@JsonValue를 이용해서 역직렬화가 이루어진다.
@Test
fun testJsonValue() {
val objectMapper = ObjectMapper().registerKotlinModule()
val json = """
{
"userType": "0"
}
""".trimIndent()
assertEquals(User.UserType.NORMAL, objectMapper.readValue<User>(json).userType)
}
댓글