2016-02-23 4 views
13

Ich habe eine Webservice, die entweder eine Liste von serialisierten MyPOJO Objekte zurückgibt:Wie können wir mit Retrofit 2 unterschiedliche Antworttypen behandeln?

[ 
    { //JSON MyPOJO }, 
    { //JSON MyPOJO } 
] 

entweder ein Fehler Objekt:

{ 
    'error': 'foo', 
    'message':'bar' 
} 

retrofit2 Verwendung, wie kann ich den Fehler abrufen?

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 
    }  
    } 
} 

ist die Gson Ausnahme:

java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ 

Retrofit-Instanz verwendet GsonConverterFactory

+0

schon gefragt http://stackoverflow.com/questions/24279245/how-to-handle-dynamic-json-in-retrofit – Rohit5k2

Antwort

10

geschaffen hatte ich ein ähnliches Problem und ich löste es durch eine generische Object verwenden und dann welche Prüfung Art von Antwort, die ich mit instanceof hatte

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 In meinem Fall hatte ich entweder MyPOJO oder MyError zurück und ich konnte sicher sein, dass es einer von diesen sein würde.

In anderen Fällen hatte ich dann das Backend das gleiche Response Object zurückgeben, egal ob die Anfrage erfolgreich war oder nicht.
Dann in diesem Antwortobjekt hatte ich meine tatsächlichen Daten in einem "Objekt" -Feld. Dann kann ich Instanz von verwenden, um zu bestimmen, welche Art von Daten ich hatte. In diesem Fall hatte ich immer das gleiche Objekt zurückgegeben, egal was der Anruf war.

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; 
} 
3
Call<LoginResponse> call = apiService.getUserLogin(usernametext, passwordtext); 
    call.enqueue(new Callback<LoginResponse>() { 
     @Override 
     public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) { 
      Log.e("responsedata","dd"+response.toString()); 
      if (response.code()==200) { 
       showMessage(response.body().getMessage()); 
       Intent intent = new Intent(LoginActivity.this, MainAct.class); 
       startActivity(intent); 
      } 
      else 
       try { 
        LoginError loginError= gson.fromJson(response.errorBody().string(),LoginError.class); 
        showMessage(loginError.getMessage()); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
     } 

     @Override 
     public void onFailure(Call<LoginResponse> call, Throwable t) { 

     } 
    }); 
} 
+1

Gut geschrieben Lösung – Gabriel