如何使用Retrofit 2处理错误响应?

时间:2017-04-10 11:39:36

标签: android json retrofit2

如何使用同步请求使用Retrofit 2处理错误响应?

我需要进程响应,在正常情况下返回pets数组,如果请求有错误的参数,则返回错误json对象。我该如何处理这两种情况?

我正在尝试使用this教程,但主要问题是将普通和错误json映射到对象。

我的正常回复示例:

[ {
    "type" : "cat",
    "color": "black"
}, 
{
    "type" : "cat",
    "color": "white"
} ]

错误回复示例:

{"error" = "-1", error_description = "Low version"}

我得到了什么:

    Call<List<Pet>> call = getApiService().getPet(1);
    Response<List<Pet>> response;
    List<Pet> result = null;

    try {
        response = call.execute(); //line with exception "Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path"
        if(!response.isSuccessful()){
            Error error = parseError(response);
            Log.d("error message", error.getErrorDescription());
        }
        if (response.code() == 200) {
            result = response.body();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

3 个答案:

答案 0 :(得分:1)

Retrofit 2处理“成功”请求的概念与Retrofit 1不同。在Retrofit 2中,所有可以执行(发送到API)并且您收到响应的请求都被视为“成功” 。这意味着,对于这些请求,将触发onResponse回调,您需要手动检查请求是否实际成功(状态200-299)或错误(状态400-599)。

如果请求成功完成,我们可以使用响应对象并执行我们想要的任何操作。如果错误实际失败(请记住,状态为400-599),我们希望向用户显示有关该问题的适当信息。

有关详细信息,请参阅此link

答案 1 :(得分:1)

我认为您应该创建一个通用的响应类(例如GenericResponse),并通过特定的响应类(例如PetResponse)对其进行扩展。在第一个属性中,包含通用属性(errorerror_description),在后一个属性中,放置特定的响应数据(List<Pet>)。

在您的情况下,我会选择这样的内容:

class GenericResponse {
   int error;
   String error_description;
} 

class PetResponse extends GenericResponse {
   List<Pet> data;
}

因此,您成功的响应正文应如下所示:

{
   "data": [ {
        "type" : "cat",       
        "color": "black"
      }, 
      {
        "type" : "cat",
        "color": "white"
      } ]
}

您的错误响应正文应如下所示:

{ "error" = "-1", error_description = "Low version"}

最后,从API调用返回的响应对象应该是:

   Response<PetResponse> response;

答案 2 :(得分:1)

在经历了许多解决方案之后。我发布它以供更动态的使用。希望这对你们有帮助。

我的错误响应

{
"severity": 0,
"errorMessage": "Incorrect Credentials (Login ID or Passowrd)"
}

下面是正常调用方法

private void makeLoginCall() {
    loginCall = RetrofitSingleton.getAPI().sendLogin(loginjsonObject);
    loginCall.enqueue(new Callback<Login>() {
        @Override
        public void onResponse(Call<Login> call, Response<Login> response) {
            if (response != null && response.code() == 200){
                //Success handling
            }
            else if (!response.isSuccessful()){
                mServerResponseCode = response.code();
                Util.Logd("In catch of login else " + response.message());
                /*
                * Below line send respnse to Util class which return a specific error string
                * this error string is then sent back to main activity(Class responsible for fundtionality)
                * */

                mServerMessage = Util.parseError(response) ;
                mLoginWebMutableData.postValue(null);
                loginCall = null;
            }
        }

        @Override
        public void onFailure(Call<Login> call, Throwable t) {
            Util.Logd("In catch of login " + t.getMessage());
            mLoginWebMutableData.postValue(null);
            mServerMessage = t.getMessage();
            loginCall = null;
        }
    });
}

下面是处理解析的util类

public static String parseError(Response<?> response){
    String errorMsg = null;
    try {
        JSONObject jObjError = new JSONObject(response.errorBody().string());
        errorMsg = jObjError.getString("errorMessage");
        Util.Logd(jObjError.getString("errorMessage"));
        return errorMsg ;
    } catch (Exception e) {
        Util.Logd(e.getMessage());
    }
    return errorMsg;
}

在viewModel观察者下方

private void observeLogin() {
    loginViewModel.getmLoginVModelMutableData().observe(this, login -> {
        if (loginViewModel.getSerResponseCode() != null) {
            if (loginViewModel.getSerResponseCode().equals(Constants.OK)) {
                if (login != null) {
                    //Your logic here
                }
            }
           //getting parsed response message from client to handling class
            else {
                Util.stopProgress(this);
                Snackbar snackbar = Snackbar.make(view, loginViewModel.getmServerVModelMessage(), BaseTransientBottomBar.LENGTH_INDEFINITE).setAction(android.R.string.ok, v -> { });
                snackbar.show();
            }
        } else {
            Util.stopProgress(this);
            Snackbar snackbar = Snackbar.make(view, "Some Unknown Error occured", BaseTransientBottomBar.LENGTH_INDEFINITE).setAction(android.R.string.ok, v -> { });
            snackbar.show();
        }
    });
}