Retrofit 2.0 how to get deserialised error response.body

前端 未结 21 2069
庸人自扰
庸人自扰 2020-11-28 02:46

I\'m using Retrofit 2.0.0-beta1.

In tests i have an alternate scenario and expect error HTTP 400

I would like to have retrofit.Respons

相关标签:
21条回答
  • 2020-11-28 03:12

    errorBody values should set APIError object in Retrofit. So that, you can use the below code structure.

    public class APIErrorUtils {
    
        public static APIError parseError(Response<?> response) {
            Converter<ResponseBody, APIError> converter = API.getClient().responseBodyConverter(APIError.class, new Annotation[0]);
    
            APIError error;
    
            try {
                error = converter.convert(response.errorBody());
                Log.d("SERVICELOG", "****************************************************");
                Log.d("SERVICELOG", "***** SERVICE LOG");
                Log.d("SERVICELOG", "***** TIMESTAMP: " + String.valueOf(error.getTimestamp()));
                Log.d("SERVICELOG", "***** STATUS: " + String.valueOf(error.getStatus()));
                Log.d("SERVICELOG", "***** ERROR: " + error.getError());
                Log.d("SERVICELOG", "***** MESSAGE: " + error.getMessage());
                Log.d("SERVICELOG", "***** PATH: " + error.getPath());
                Log.d("SERVICELOG", "****************************************************");
            } catch (IOException e) {
                return new APIError();
            }
    
            return error;
        }
    }
    
    APIError error = APIErrorUtils.parseError(response);
    if (error.getStatus() == 400) {
        ....
    }
    
    0 讨论(0)
  • 2020-11-28 03:13

    This way you do not need a Retrofit instance if you only are injecting a service created from Retrofit.

    public class ErrorUtils {
    
      public static APIError parseError(Context context, Response<?> response) {
    
        APIError error = new APIError();
    
        try {
            Gson gson = new Gson();
            error = gson.fromJson(response.errorBody().charStream(), APIError.class);
        } catch (Exception e) {
            Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
        }
    
        if (TextUtils.isEmpty(error.getErrorMessage())) {
            error.setError(response.raw().message());
        }
        return error;
      }
    }
    

    Use it like this:

    if (response.isSuccessful()) {
    
          ...
    
        } else {
    
          String msg = ErrorUtils.parseError(fragment.getActivity(), response).getError(); // would be from your error class
          Snackbar.make(someview, msg, Snackbar.LENGTH_LONG).show();
        }
      }
    
    0 讨论(0)
  • 2020-11-28 03:14

    I solved it by:

     if(!response.isSuccessful()){
           Gson gson = new Gson();
           MyErrorMessage message=gson.fromJson(response.errorBody().charStream(),MyErrorMessage.class);
           if(message.getCode()==ErrorCode.DUPLICATE_EMAIL_ID_CODE){
                      //DO Error Code specific handling                        
            }else{
                     //DO GENERAL Error Code Specific handling                               
            }
        }
    

    MyErrorMessage Class:

      public class MyErrorMessage {
         private int code;
         private String message;
    
         public int getCode() {
            return code;
         }
    
         public void setCode(int code) {
            this.code = code;
         }
    
         public String getMessage() {
             return message;
         }
    
         public void setMessage(String message) {
            this.message = message;
         }
       }
    
    0 讨论(0)
  • 2020-11-28 03:16

    In Retrofit 2.0 beta2 this is the way that I'm getting error responses:

    1. Synchronous

      try {
         Call<RegistrationResponse> call = backendServiceApi.register(data.in.account, data.in.password,
                 data.in.email);
         Response<RegistrationResponse> response = call.execute();
         if (response != null && !response.isSuccess() && response.errorBody() != null) {
             Converter<ResponseBody, BasicResponse> errorConverter =
                     MyApplication.getRestClient().getRetrofitInstance().responseConverter(BasicResponse.class, new Annotation[0]);
             BasicResponse error = errorConverter.convert(response.errorBody());
             //DO ERROR HANDLING HERE
             return;
         }
         RegistrationResponse registrationResponse = response.body();
         //DO SUCCESS HANDLING HERE
      } catch (IOException e) {
         //DO NETWORK ERROR HANDLING HERE
      }
      
    2. Asynchronous

      Call<BasicResponse> call = service.loadRepo();
      call.enqueue(new Callback<BasicResponse>() {
          @Override
          public void onResponse(Response<BasicResponse> response, Retrofit retrofit) {
              if (response != null && !response.isSuccess() && response.errorBody() != null) {
                  Converter<ResponseBody, BasicResponse> errorConverter =
                      retrofit.responseConverter(BasicResponse.class, new Annotation[0]);
                  BasicResponse error = errorConverter.convert(response.errorBody());
                  //DO ERROR HANDLING HERE
                  return;
              }
              RegistrationResponse registrationResponse = response.body();
              //DO SUCCESS HANDLING HERE
          }
      
          @Override
          public void onFailure(Throwable t) {
              //DO NETWORK ERROR HANDLING HERE
          }
      });
      

    Update for Retrofit 2 beta3:

    1. Synchronous - not changed
    2. Asynchronous - Retrofit parameter was removed from onResponse

      Call<BasicResponse> call = service.loadRepo();
      call.enqueue(new Callback<BasicResponse>() {
          @Override
          public void onResponse(Response<BasicResponse> response) {
              if (response != null && !response.isSuccess() && response.errorBody() != null) {
                  Converter<ResponseBody, BasicResponse> errorConverter =
                      MyApplication.getRestClient().getRetrofitInstance().responseConverter(BasicResponse.class, new Annotation[0]);
                  BasicResponse error = errorConverter.convert(response.errorBody());
                  //DO ERROR HANDLING HERE
                  return;
              }
              RegistrationResponse registrationResponse = response.body();
              //DO SUCCESS HANDLING HERE
          }
      
          @Override
          public void onFailure(Throwable t) {
              //DO NETWORK ERROR HANDLING HERE
          }
      });
      
    0 讨论(0)
  • 2020-11-28 03:18

    Create a model of the Error response & user Gson to convert the response to it. This will just work fine.

    APIError.java

    public class APIError {
        private String message;
    
        public String getMessage() {
            return message;
        }
    }
    

    MainActivity.java (inside request onResponse)

    if (response.isSuccessful()) {
        // Do your success stuff...
    
    } else {
        APIError message = new Gson().fromJson(response.errorBody().charStream(), APIError.class);
        Toast.makeText(MainActivity.this, "" + message.getMessage(), Toast.LENGTH_SHORT).show();
    }
    
    0 讨论(0)
  • 2020-11-28 03:18

    Tested and works

     public BaseModel parse(Response<BaseModel> response , Retrofit retrofit){
                BaseModel error = null;
                Converter<ResponseBody, BaseModel> errorConverter =
                        retrofit.responseBodyConverter(BaseModel.class, new Annotation[0]);
                try {
                    if (response.errorBody() != null) {
                        error = errorConverter.convert(response.errorBody());
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return error;
            }
    
    0 讨论(0)
提交回复
热议问题