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
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)`
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) {
}
})
solved it by:
Converter<MyError> converter =
(Converter<MyError>)JacksonConverterFactory.create().get(MyError.class);
MyError myError = converter.fromBody(response.errorBody());
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);
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.
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)