@JsonCreator 주의사항
Spring 환경에서는 일반적으로 api body 포맷으로 json 을 사용하고 전달받은 json 문자열의 역직렬화도 자동으로 지원한다. 그런데 역직렬화 함수를 직접 구현해서 유효성 검증에 활용하고 싶은 경우 해당 클래스의 static 팩토리 함수에 @JsonCreator 를 명시해주면 된다.
코틀린 환경을 기준으로 아래와 같이 구현할 수 있다.
data class AuthMsgReqInfo private constructor(
val recieverNumber: String,
val senderNumber: String,
var content:String,
val pocId: String?,
val origin: Origin?
) {
companion object {
@JsonCreator
@JvmStatic
fun of(
recieverNumber: String?,
senderNumber: String?,
content: String?,
pocId: String?,
origin: Origin?): AuthMsgReqInfo =
when {
recieverNumber.isNullOrBlank() ->
throw InmsException("'recieverNumber' is required")
!content.isNullOrBlank() && !content.contains("\${authKey}") ->
throw InmsException("'content' must contain \${authKey}")
else ->
AuthMsgReqInfo(
recieverNumber = recieverNumber!!,
senderNumber = senderNumber ?: "15667727",
content = if(content.isNullOrBlank()) "인증번호 \${authKey} 을 입력해주세요." else content,
pocId = pocId,
origin = origin
)
}
}
}
그런데 이때 클래스의 맴버변수는 기본적으로 모두 static 팩토리 함수의 파라미터로 포함되어야 한다.
예를 들어 AuthMsgReqInfo의 맴버변수 중 content 값을 무조건 디폴트 문자열로 할당하기 위해 코드를 아래와 같이 바꿨다고 가정해보자.
data class AuthMsgReqInfo private constructor(
val recieverNumber: String,
val senderNumber: String,
var content:String,
val pocId: String?,
val origin: Origin?
) {
companion object {
@JsonCreator
@JvmStatic
fun of(
recieverNumber: String?,
senderNumber: String?,
// content: String?,
pocId: String?,
origin: Origin?): AuthMsgReqInfo =
when {
recieverNumber.isNullOrBlank() ->
throw InmsException("'recieverNumber' is required")
// !content.isNullOrBlank() && !content.contains("\${authKey}") ->
// throw InmsException("'content' must contain \${authKey}")
else ->
AuthMsgReqInfo(
recieverNumber = recieverNumber!!,
senderNumber = senderNumber ?: "15667727",
// content = if(content.isNullOrBlank()) "인증번호 \${authKey} 을 입력해주세요." else content,
content = "인증번호 \${authKey} 을 입력해주세요.",
pocId = pocId,
origin = origin
)
}
}
}
request 와 무관하게 디폴트 값을 할당할 것이니 팩토리 함수의 파라미터에서도 제거되고 객체 생성시에만 포함하도록 했다. 표면적으로 딱히 문제는 없어보인다.
실제로 아래와 같은 json 을 requst body 로 보내면 지정한 특정 문자열이 잘 셋팅된다.
{
"recieverNumber": "01051641035",
"senderNumber": "15667727",
"pocId": null,
"origin": null
}
그런데 문제는 json 이 아래와 같을 경우다.
{
"recieverNumber": "01051641035",
"senderNumber": "15667727",
"content": "test",
"pocId": null,
"origin": null
}
content 를 "test" 로 할당해서 보냈지만 팩토리 함수에서 이를 활용하지 않고 역직렬화를 수행했으니 디폴트 문자열이 셋팅되었을 거 같지만 실제 역직렬화 되는 값은 "test" 다.
예상해보면 request 로 받은 json 값에 대해 1차적으로 @JsonCreator 로 지정된 팩토리 함수로 역직렬화를 수행하고 역직렬화되지 못한 데이터는 spring의 기본 역직렬화 정책에 따라 매핑된 key 값에 할당되는 것 같다.
이처럼 @JsonCreator 를 지정한 함수에서 맴버변수를 모두 처리하지 않으면 의도치 않은 데이터가 역직렬화에 포함될 수 있으니 주의가 필요하다.