Hesam Hesam - 6 months ago 65
Android Question

Retrofit2, how to convert response to base class?

I have base class for my responses. This class gets called when there is a problem (such as authentications problem).

public class DefaultResponse
{
private transient Integer status;
private String property;
private String message;
private String developerMessage;
protected String code;

public void setResponse(final Response response)
{
if (this.status != null)
{
return;
}

if (response != null)
{
try
{
final Object obj = response.body();
if (obj != null && obj instanceof DefaultResponse)
{
this.status = response.code();
this.message = ((DefaultResponse) obj).message;
this.developerMessage = ((DefaultResponse) obj).developerMessage;
this.property = ((DefaultResponse) obj).property;
this.code = ((DefaultResponse) obj).code;
}
}
catch (final Exception ignored)
{

}
}
}

...
}


The rest of Responses are extending this class.

public class FeatureResponse extends DefaultResponse
{
// Implementation
}


This is the method I'm using to call the API in order to get Features.

public void getFeatures(final Location location)
{
Call<FeatureResponse> call = mService.getPassengerFeatures(location);
call.enqueue(new Callback<FeatureResponse>()
{
@Override
public void onResponse(Call<FeatureResponse> call, Response<FeatureResponse> response)
{
Logger.debug("Test", "Instance of response: " + response.getClass());

FeatureResponse featureResponse = new FeatureResponse();

if (response.isSuccessful())
{
//...
}

featureResponse.setResponse(response);
EventBus.post(featureResponse);
}

@Override
public void onFailure(Call<FeatureResponse> call, Throwable t)
{
Logger.error(TAG, "getPassengerFeatures.onFailure(), msg: " + t.getMessage());

FeatureResponse featureResponse = new FeatureResponse();
featureResponse.setFailure(t);
EventBus.post(featureResponse);
}
});
}


When I send the request, this is my server response:

{"status":403,"code":4030,"property":"","message":"Unauthorized access","developerMessage":"Unauthorized access"}


Therefore,
onResponse
gets called, new object of
FeatureResponse
gets created and
featureResponse.setResponse(response);
gets called. As you see in above code I'm trying to get its HTTP status code. However, the problem is
if (obj != null && obj instanceof DefaultResponse)
is always
false
as
response
is Instance of class retrofit2.Response.

Is it possible to convert
Response
to
DefaultResponse
?

Answer

When i am getting error such as 401 , 400 am using this way with Gson :

if (response.code() == 400) 
{
   Gson gson = new GsonBuilder().create();
   MyPojoError myPojoError=new MyPojoError ();
   try {
         myPojoError= gson.fromJson(response.errorBody().string(),MyPojoError .class);
        } catch (IOException e) {  // handle failure to read error   }

}

Also you need annotations when converting response to Pojo with Gson :

public class MyPojoError {

@SerializedName("error")
@Expose
private String error;
@SerializedName("error_description")
@Expose
private String errorDescription;

/**
 *
 * @return
 * The error
 */
public String getError() {
    return error;
}

/**
 *
 * @param error
 * The error
 */
public void setError(String error) {
    this.error = error;
}

/**
 *
 * @return
 * The errorDescription
 */
public String getErrorDescription() {
    return errorDescription;
}

/**
 *
 * @param errorDescription
 * The error_description
 */
public void setErrorDescription(String errorDescription) {
    this.errorDescription = errorDescription;
}

}

Paste your example Json response to site , select source type JSON , annotation : Gson : Json Schema to Pojo

In your build.gradle : compile 'com.google.code.gson:gson:2.6.2'