Retrofit 2.0 how to get deserialised error response.body

前端 未结 21 2070
庸人自扰
庸人自扰 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:18
    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)`
    
    0 讨论(0)
  • 2020-11-28 03:19

    In Kotlin:

    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) {
        }
    })
    
    0 讨论(0)
  • 2020-11-28 03:20

    solved it by:

    Converter<MyError> converter = 
        (Converter<MyError>)JacksonConverterFactory.create().get(MyError.class);
    MyError myError =  converter.fromBody(response.errorBody());
    
    0 讨论(0)
  • 2020-11-28 03:22

    ErrorResponse is your custom response object

    Kotlin

    val gson = Gson()
    val type = object : TypeToken<ErrorResponse>() {}.type
    var errorResponse: ErrorResponse? = gson.fromJson(response.errorBody()!!.charStream(), type)
    

    Java

    Gson gson = new Gson();
    Type type = new TypeToken<ErrorResponse>() {}.getType();
    ErrorResponse errorResponse = gson.fromJson(response.errorBody.charStream(),type);
    
    0 讨论(0)
  • 2020-11-28 03:25

    It's actually very straight forward.

    Kotlin:

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

    Java:

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

    Tested on retrofit:2.5.0. Read the text from the charStream which will give you a String, then parse to JSONObject.

    Adios.

    0 讨论(0)
  • 2020-11-28 03:27

    Here is elegant solution using Kotlin extensions:

    data class ApiError(val code: Int, val message: String?) {
        companion object {
            val EMPTY_API_ERROR = ApiError(-1, null)
        }
    }
    
    fun Throwable.getApiError(): ApiError? {
        if (this is HttpException) {
            try {
                val errorJsonString = this.response()?.errorBody()?.string()
                return Gson().fromJson(errorJsonString, ApiError::class.java)
            } catch (exception: Exception) {
                // Ignore
            }
        }
        return EMPTY_API_ERROR
    }
    

    and usage:

    showError(retrofitThrowable.getApiError()?.message)

    0 讨论(0)
提交回复
热议问题