Retrofit 2 how to handle server response that's sometimes Void sometimes Non-Void

Viewed 714

When I make a login request through Retrofit2 that succeeds, I get an empty body. However when the login fails for whatever reason, the response returns a JSON body like this: { message: "error message"}.

The issue is as follows, if I model the call like this:

 interface LoginAPIService {
    @POST("login")
    fun login(@Body body: RequestBody): Call<LoginResponse>
}

I will get an EOF failure when the body returned is null, however if I model the call as:

interface LoginAPIService {
    @POST("login")
    fun login(@Body body: RequestBody): Call<Void>
}

then I will not receive the error message, which must be printed out for the user. Please suggest how to handle this odd case.

2 Answers

First try using Call<Response<LoginResponse>> (caution: make sure it's Retrofit Response<>, not OkHttp Response). Then you get "success" callback in all cases, so then you do

if(it.isSuccessful) 
    return it.body
else
    parseErrorJson(it.errorBody().byteStream()) //.bytestream() for GSon, .source() for Moshi

Where parseErrorJson interprets the body of the error.

If all errors have the same format, you can put similar code into an interceptor.

At best, wrap the error object into custom exception and throw it.

The way I resolved this issue is by making the call from okhttp3. That way my onSuccess was correct and the way I got the error message was using

val jObjError = JSONObject(response.errorBody()!!.string())
                    
loginLiveData.postValue(jObjError.get("message").toString())
Related