180

Retrofit 2.0.0-beta1を使用しています。

テストでは、別のシナリオがあり、エラー HTTP 400 が予想されます

したいのですがretrofit.Response<MyError> responseresponse.body() == null

MyError はデシリアライズされていません - ここでしか見えません

response.errorBody().string()

しかし、それは私に MyError をオブジェクトとして与えません

4

26 に答える 26

182

私は現在、コンバーターや特別なクラスを使用する必要のない、非常に簡単な実装を使用しています。私が使用するコードは次のとおりです。

public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
    DialogHelper.dismiss();

    if (response.isSuccessful()) {
        // Do your success stuff...
    } else {
        try {
            JSONObject jObjError = new JSONObject(response.errorBody().string());
            Toast.makeText(getContext(), jObjError.getJSONObject("error").getString("message"), Toast.LENGTH_LONG).show();
        } catch (Exception e) {
            Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }
}

ここで注意すべき点はresponse.errorBody().string()、正しい値が 1 回だけ返されることです。もう一度呼び出すと、空の文字列が返されます。したがって、再利用する場合は、最初の呼び出しで値を変数に格納します。

于 2016-07-07T10:56:37.503 に答える
31

Retrofit 2.0 beta2 では、これがエラー応答を取得する方法です。

  1. 同期

    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. 非同期

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

Retrofit 2 beta3 の更新:

  1. 同期 - 変更なし
  2. 非同期 - onResponse から Retrofit パラメータが削除されました

    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
        }
    });
    
于 2015-10-01T20:13:27.033 に答える
31

それは実際には非常に簡単です。

コトリン:

val jsonObj = JSONObject(response.errorBody()!!.charStream().readText())
responseInterface.onFailure(jsonObj.getString("msg"))

ジャワ:

    if(response.errorBody()!=null){
    JSONObject jsonObj = new JSONObject(TextStreamsKt.readText(response.errorBody().charStream()));
        responseInterface.onFailure(jsonObj.getString("msg"));
    }else{
        responseInterface.onFailure("you might want to return a generic error message.");
    }

レトロフィットでテスト済み:2.5.0。文字列を取得する charStream からテキストを読み取り、JSONObject に解析します。

アディオス。

于 2020-05-15T00:32:30.327 に答える
11
 @Override
 public void onResponse(Call<Void> call, retrofit2.Response<Void> response) {
            if (response.isSuccessful()) {

            //Do something if response is ok
            } else {

                JsonParser parser = new JsonParser();
                JsonElement mJson = null;
                try {
                    mJson = parser.parse(response.errorBody().string());
                    Gson gson = new Gson();
                    MyError errorResponse = gson.fromJson(mJson, MyError.class);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }
于 2017-05-26T15:35:08.363 に答える
10

https://stackoverflow.com/a/21103420/2914140およびhttps://futurestud.io/tutorials/retrofit-2-simple-error-handlingでは、このバリアントは Retrofit 2.1.0 に対して示されています。

call.enqueue(new Callback<MyResponse>() {
    @Override
    public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
        if (response.isSuccessful()) {
            ...
        } else {
            Converter<ResponseBody, MyError> converter
                    = MyApplication.getRetrofit().responseBodyConverter(
                    MyError.class, new Annotation[0]);
            MyError errorResponse = null;
            try {
                errorResponse = converter.convert(response.errorBody());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
于 2016-09-18T17:45:14.627 に答える
6

Retrofit 2.0-beta2 を使用した非同期呼び出しでは、次のようにしました。

@Override
public void onResponse(Response<RegistrationResponse> response, 
                       Retrofit retrofit) {
    if (response.isSuccess()) {
        // Do success handling here
    } else {
        try {
            MyError myError = (MyError)retrofit.responseConverter(
                    MyError.class, MyError.class.getAnnotations())
                .convert(response.errorBody());
            // Do error handling here
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
于 2015-10-21T15:32:49.587 に答える
0

それを解決しました:

Converter<MyError> converter = 
    (Converter<MyError>)JacksonConverterFactory.create().get(MyError.class);
MyError myError =  converter.fromBody(response.errorBody());
于 2015-09-11T10:06:29.713 に答える
0

errorBody 値は Retrofit で APIError オブジェクトを設定する必要があります。そのため、以下のコード構造を使用できます。

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) {
    ....
}
于 2018-03-28T12:39:16.403 に答える
0
val error = JSONObject(callApi.errorBody()?.string() as String)
            CustomResult.OnError(CustomNotFoundError(userMessage = error["userMessage"] as String))

open class CustomError (
    val traceId: String? = null,
    val errorCode: String? = null,
    val systemMessage: String? = null,
    val userMessage: String? = null,
    val cause: Throwable? = null
)

open class ErrorThrowable(
    private val traceId: String? = null,
    private val errorCode: String? = null,
    private val systemMessage: String? = null,
    private val userMessage: String? = null,
    override val cause: Throwable? = null
) : Throwable(userMessage, cause) {
    fun toError(): CustomError = CustomError(traceId, errorCode, systemMessage, userMessage, cause)
}


class NetworkError(traceId: String? = null, errorCode: String? = null, systemMessage: String? = null, userMessage: String? = null, cause: Throwable? = null):
    CustomError(traceId, errorCode, systemMessage, userMessage?: "Usted no tiene conexión a internet, active los datos", cause)

class HttpError(traceId: String? = null, errorCode: String? = null, systemMessage: String? = null, userMessage: String? = null, cause: Throwable? = null):
    CustomError(traceId, errorCode, systemMessage, userMessage, cause)

class UnknownError(traceId: String? = null, errorCode: String? = null, systemMessage: String? = null, userMessage: String? = null, cause: Throwable? = null):
    CustomError(traceId, errorCode, systemMessage, userMessage?: "Unknown error", cause)

class CustomNotFoundError(traceId: String? = null, errorCode: String? = null, systemMessage: String? = null, userMessage: String? = null, cause: Throwable? = null):
    CustomError(traceId, errorCode, systemMessage, userMessage?: "Data not found", cause)`
于 2020-01-27T21:40:01.000 に答える
0

コトリンでは:

val call = APIClient.getInstance().signIn(AuthRequestWrapper(AuthRequest("1234567890z", "12341234", "nonce")))
call.enqueue(object : Callback<AuthResponse> {
    override fun onResponse(call: Call<AuthResponse>, response: Response<AuthResponse>) {
        if (response.isSuccessful) {

        } else {
            val a = object : Annotation{}
            val errorConverter = RentalGeekClient.getRetrofitInstance().responseBodyConverter<AuthFailureResponse>(AuthFailureResponse::class.java, arrayOf(a))
            val authFailureResponse = errorConverter.convert(response.errorBody())
        }
    }

    override fun onFailure(call: Call<AuthResponse>, t: Throwable) {
    }
})
于 2017-06-04T23:48:25.800 に答える