2016-02-23 8 views
13

Mam usługa, która zwraca albo listę obiektów MyPOJO odcinkach:W jaki sposób możemy obsłużyć inny typ reakcji z Retrofit 2?

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

albo obiekt błędu:

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

Korzystanie retrofit2, jak mogę odzyskać błąd?

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

Oto wyjątek GSON:

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

instancja Modernizacja jest tworzony przy użyciu GsonConverterFactory

+0

Już poprosił http://stackoverflow.com/questions/24279245/how-to-handle-dynamic-json-in-retrofit – Rohit5k2

Odpowiedz

10

miałem podobny problem i rozwiązać go za pomocą rodzajowe Object a następnie testowanie jaki rodzaj Odpowiedź: Wystąpiłam z wystąpieniem:

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 w moim przypadku wróciłem MyPOJO lub MyError i mogłem być pewien, że będzie to jedna z nich.

W innych przypadkach zwróciłem backendowi ten sam obiekt odpowiedzi, niezależnie od tego, czy żądanie się powiodło, czy nie.
Następnie wewnątrz tego obiektu odpowiedzi miałem rzeczywiste dane w polu "Obiekt". Następnie mogę użyć instancji, aby określić, jaki typ danych miałem. W tym przypadku zawsze zwracano ten sam przedmiot, bez względu na to, jakie było połączenie.

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

dobrze napisana rozwiązanie – Gabriel