J'ai un webservice qui renvoie soit une liste d'objets sérialisés MyPOJO:
[
{ //JSON MyPOJO },
{ //JSON MyPOJO }
]
soit un objet d'erreur:
{
'error': 'foo',
'message':'bar'
}
À l'aide de 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
}
}
}
Voici l'exception GSON:
Java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
L'instance de modification est créée à l'aide de GsonConverterFactory
J'ai eu un problème similaire et je l'ai résolu en utilisant un générique Object
puis en testant le type de réponse que j'ai eu 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 mon cas, j'avais renvoyé MyPOJO ou MyError et je pouvais être sûr que ce serait l'un d'entre eux.
Dans d'autres cas, le backend a renvoyé le même objet de réponse, que la demande soit réussie ou non.
Puis, à 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 le type de données que j'avais. Dans ce cas, j'ai toujours eu le même objet retourné, quel que soit 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;
}
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) {
}
});
}