2016-02-23 2 views
13

J'ai un webservice qui retourne soit une liste d'objets MyPOJO sérialisés:Comment pouvons-nous gérer différents types de réponses avec Retrofit 2?

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

soit un objet d'erreur:

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

En utilisant retrofit2, comment puis-je récupérer l'erreur?

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

est ici l'exception GSON:

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

instance Rénovation est créé en utilisant GsonConverterFactory

+0

déjà demandé http://stackoverflow.com/questions/24279245/how-to-handle-dynamic-json-in-retrofit – Rohit5k2

Répondre

10

J'ai eu un problème similaire et je l'ai résolu en utilisant un Object générique puis tester ce type de réponse que j'avais en utilisant 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 
    } 
}); 

Dans Dans mon cas, MyPOJO ou MyError étaient retournés et je pouvais être sûr que ce serait l'un de ceux-là.

Dans d'autres cas, le backend renvoyait le même objet de réponse, que la requête aboutisse ou non.
Ensuite, à l'intérieur de cet objet de réponse, j'avais mes données réelles dans un champ "Objet". Ensuite, je peux utiliser l'instance de pour déterminer quel type de données j'avais. Dans ce cas, j'ai toujours eu le même objet retourné, peu importe l'appel.

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

solution bien écrite – Gabriel