응답 모델이 상속받은 data 클래스일 때, multiple JSON fields 이슈
728x90
반응형

 

NHN 클라우드 서비스 중 SMS 발송내역을 조회하는 API를 이용하려고 했다. 서버 내 클라이언트를 만들고 호출하는 과정에서 아래와 같은 에러가 발생하면서 원하는 형태로 모델 파싱이 되지 않았다.

java.lang.IllegalArgumentException: 
class notification.MmsResponse declares multiple JSON fields named header

 

환경

  • 스프링부트3 + JPA + 코틀린
  • http3, Gson
  • NHN 클라우드 서비스 이용
fun getMmsList(recipientNo: String): MmsResponse {
    val client = OkHttpClient().newBuilder().build()
    
    // 일부 생략
    
    val request = Request.Builder()
        .url("$url/sms/v3.0/appKeys/$appKey/sender/mms?$queryParameter")
        .method("GET", null)
        .addHeader("Content-Type", "application/json;charset=UTF-8")
        .addHeader("X-Secret-Key", secretKey)
        .build()
    val response = client.newCall(request).execute()
    response.body?.let {
        val mmsResponse = Gson().fromJson(it.string(), MmsResponse::class.java) // 에러 발생 지점
        logger.info("mms received response: {}", mmsResponse)
        checkSuccessful(mmsResponse, true)
        return mmsResponse
    } ?: throw NotificationException(NotificationErrorType.MMS_RECEIVING_ERROR)
}

 

위에서 Gson으로 파싱하는 부분이 있다. 파싱하는 과정에서 본 내용의 초반에 언급한 에러가 발생했다. Response 모델을 확인할 필요가 있다.

 

 

 

Before

여러개의 응답 모델에는 동일한 header 형태를 가지고 있다. 그래서 하나의 추상클래스를 상속 받도록 응답 모델을 설계했다.

data class MmsResponse(
    override val header: NhnHeader,
    val body: Body
) : NhnMessage(header) {
  // 일부 생략
}

abstract class NhnMessage(
    open val header: NhnHeader
)

data class NhnHeader(
    val resultCode: Int,
    val resultMessage: String,
    val isSuccessful: Boolean
)

 

API 호출시 응답 JSON은 아래와 같다.

 

{
    "header": {
        "resultCode": 0,
        "resultMessage": "SUCCESS",
        "isSuccessful": true
    },
    "body": {
    	// 일부 생략
    }
}

 

오류 메세지를 읽어보면 'header'라는 이름의 필드가 여러개 있다는 것을 알 수 있다. 분명 MmsResponse에는 하나의 header만 존재한다. 하지만 JSON 파싱 과정에서 부모 클래스인 NhnMessage 클래스의 header 필드 정보도 수집하면서 이 오류가 생긴다. 이는 코틀린 모델 이슈라기보다 상속을 사용하는 과정에서 겪을 수 있는 문제이다.

 

 

After

아래와 같이 부모 클래스의 header를 nhnHeader로, 즉 다른 이름으로 수정하면 에러가 발생하지 않고 정상 작동한다.

 

data class MmsResponse(
    val header: NhnHeader, // <-- 변경
    val body: Body
) : NhnMessage(header) {
  // 일부 생략
}

abstract class NhnMessage(
    open val nhnHeader: NhnHeader // <-- 변경
)

data class NhnHeader(
    val resultCode: Int,
    val resultMessage: String,
    val isSuccessful: Boolean
)

 

 

 

참고 자료
[JAVA] IllegalArgumentException : Class 'xxx' declares multiple JSON fields named 'xxx'
728x90
반응형