2

So for some reason I need to execute my call like this:

val result = manager.call.execute()
if (result.isSuccess) {
   //do stuff
} else {
    //handle exeption
}

When my code arrives in the else bracket result.body() is null and result.errorBody() has its buffer content to 0 but not its length.

BUT, this are the log I get from retrofit :

<-- 400 Bad Request https://cubus-friends-
...
D/OkHttp: {"error":"validation_error","error_description":"No user with that phone number"}
D/OkHttp: <-- END HTTP (81-byte body)  

How can I get my json error string into the else bracket in my code ?

tufekoi
  • 929
  • 2
  • 14
  • 33
  • 1
    have you tried this : [Getting JSON from RetrofitError](http://stackoverflow.com/a/21103420/1893220) ? P.S: Look at the Retrofit 2.0 part – florian-do Apr 07 '16 at 16:01
  • OK so I didn't notice the Retrofit 2 section at the end of the comment... Thanks ! – tufekoi Apr 07 '16 at 16:32

4 Answers4

5

You can create a simple class like this

class ApiError constructor(error: Throwable) {
    var errorMessage = "An error occurred"
    var error = "error"

    init {
        if (error is HttpException) {
            val errorJsonString = error.response()
                                       .errorBody()?.string()
            parsedString = JsonParser().parse(errorJsonString)
            this.error = parsedString.asJsonObject["error"].asString
            this.errorMessage = parsedString.asJsonObject["error_message"].asString
        } else {
            this.errorMessage = error.message ?: this.errorMessage
        }
    }
}

And use it like so

try  { 
    val result = manager.call.execute()
} catch(error: IOException) {
    ApiError(error).errorMessage
}

The advantage of this approach is that you can use ApiError(error).errorMessage anywhere in your code without having to rewrite the parsing logic.

This is all from this blog post (which I wrote).

Timi Ajiboye
  • 113
  • 2
  • 8
4

As suggested by @florian-do, Getting JSON from RetrofitError contains the answer, see Retrofit2 section at the end of the answer. However, I'm using kotlin and this little change is necessary to obtain the converter :

val a = object : Annotation{}
val converter = Backend.retrofit. //this is for accessing my Retrofit object
        responseBodyConverter<Error>(Error::class.java, arrayOf(a))
Community
  • 1
  • 1
tufekoi
  • 929
  • 2
  • 14
  • 33
1

This is best way without creating unused annotation object instance

responseBodyConverter<Error>(Error::class.java, arrayOfNulls<Annotation>(0))
Igor
  • 2,039
  • 23
  • 27
0

If you want to get data when error response comes (typically a response code except 200) you can do it like that in your onResponse() method:

  if (result.isSuccess) {
  //do stuff
  } else {
  //handle exeption
      val converter = 
      ApiClient.getClient()?.responseBodyConverter<ErrorResponseData>(
                ErrorResponseData::class.java, arrayOfNulls<Annotation>(0))
                        var errorResponse: ErrorResponseData? = null
                            errorResponse = converter?.convert(response.errorBody())
                            if (errorResponse != null) {
                                //TODO: Handle Error case...
                            }
  }