I have a webservice that returns either a list of serialized MyPOJO objects:
[ { //JSON MyPOJO }, { //JSON MyPOJO } ]
either an error object :
{ 'error': 'foo', 'message':'bar' }
Using retrofit2, how can I retrieve the error ?
Call<List<MyPOJO>> request = ... request.enqueue(new Callback<List<MyPOJO>>() { @Override public void onResponse(Response<List<MyPOJO>> response) { if (response.isSuccess()) { List<MyPOJO> myList = response.body(); // do something with the list... } else { // server responded with an error, here is how we are supposed to retrieve it ErrorResponse error = ErrorResponse.fromResponseBody(apiService.getRetrofitInstance(), response.errorBody()); processError(error); // but we never get there because GSON deserialization throws an error ! } } @Override public void onFailure(Throwable t) { if(t instanceof IOException){ // network error }else if(t instanceof IllegalStateException){ // on server sending an error object we get there // how can I retrieve the error object ? }else { // default error handling } } }
Here is the GSON exception:
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
Retrofit instance is created using GsonConverterFactory
Retrofit is a REST Client for Java and Android allowing to retrieve and upload JSON (or other structured data) via a REST based You can configure which converters are used for the data serialization, example GSON for JSON.
I had a similar issue and I solved it by using a generic Object
and then testing what type of response I had using instanceof
Call<Object> call = api.login(username, password); call.enqueue(new Callback<Object>() { @Override public void onResponse(Response<Object> response, Retrofit retrofit) { if (response.body() instanceof MyPOJO ) { MyPOJO myObj = (MyPOJO) response.body(); //handle MyPOJO } else //must be error object { MyError myError = (MyError) response.body(); //handle error object } } @Override public void onFailure(Throwable t) { ///Handle failure } });
In my case I had either MyPOJO or MyError returned and I could be sure it would be one of these.
In other cases then I had the backend return the same Response Object no matter if the request was successful or not.
Then inside this response object I had my actual data within an "Object" field. Then I can use instance of to determine what type of data I had. In this case I always had the same object being returned, no matter what the call was.
public class MyResponse { private int responseCode; private String command; private int errorno; private String errorMessage; private Object responseObject; //This object varies depending on what command was called private Date responseTime; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With