Nuke Olaf - Log Store

[Android] 안드로이드 - 레트로핏 errorbody() 파싱하기 본문

Android

[Android] 안드로이드 - 레트로핏 errorbody() 파싱하기

NukeOlaf 2020. 4. 14. 23:07

현재 나는 retrofit 을 사용하여 Metaler 서버와 통신하고 있다.

클라이언트 측에서 잘못된 request 를 보내거나, 서버 측에서 뭔가 문제가 있을때
body() 는 null 로 오고, errorbody() 에 에러 코드가 정의되어 돌아오도록 되어있다.

레트로핏은 응답의 Http 상태코드가 200이던 400이던 상관없이
통신이 성공하기만 하면 onResponse() 콜백을 타게 되므로
(인터넷 장애로 인한 통신 실패일 경우만 onFailure() 콜백을 탄다)
onResponse() 에서도
if (body != null && response.isSuccessful) 이런식으로
상태코드가 200이고, 응답이 null 값이 아닌지 확인을 해줘야 한다.

아래는 response 를 검증하는 회원가입 API 를 사용하는 코드의 일부이다.

retrofitClient.addUser(request).enqueue(object : Callback<AddUserResponse> {
            override fun onResponse(
                call: Call<AddUserResponse>,
                response: Response<AddUserResponse>
            ) {
                val body = response.body()
                if (body != null && response.isSuccessful) {
                    callback.onUserAdded(body)
                } else {
                    callback.onResponseError(response.errorbody())
                }
            }

            override fun onFailure(call: Call<AddUserResponse>, t: Throwable) {
                callback.onFailure(t)
            }
        })

그런데 문제가 있었다.

response.errorbody() 를 Toast 메시지로 띄우려고 하는데

errorbody() 내용이
okhttp3.ResponseBody$Companion$asResponseBody$1@f49d60a
이런식으로 알 수 없는 문장이 나왔다.

okhttp 로깅 인터셉터에서는 분명히 제대로된 에러코드가 있는데
왜 저런 문제가 생기는지 찾아보았더니

response.errorbody() 는 RequestBody? 타입으로 돌아오게 되며,
RequestBody 는 미리 정의된 data class 로 convert 되어야 사용 가능하단다;;

그래서 NetworkUtil 이라는 클래스를 만들고,
errorbody 를 convert 해주는 함수를 만들어 사용했다.

object NetworkUtil {
    fun getErrorResponse(errorBody: ResponseBody): ErrorResponse {
        return RetrofitClient.retrofit.responseBodyConverter<ErrorResponse>(
            ErrorResponse::class.java,
            ErrorResponse::class.java.annotations
        ).convert(errorBody)
    }
}

RetrofitClient.retrofit 은 아래와 같다.

object RetrofitClient {
    val client: RetrofitInterface
    val retrofit: Retrofit
    private const val BASE_URL = "http://metaler.kr/"

    init {
        ...

        retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

        ...
    }
}

 

Comments