retrofit: Converting response.errorBody()

Can somebody provide example of converting response.errorBody() to some Error class or String or JSON ? I’ve tried this kind of converter and this approach, but i always get null ?

In my case server responds with

"Message": "Authorization has been denied for this request."

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 1
  • Comments: 23 (4 by maintainers)

Most upvoted comments

I found a better way to convert errorbody to JSONObject if you dont have time for creating ResponseError classes. Just do JSONObject jObjError = new JSONObject (response.errorBody().string())

No silly converter required, no bufferedreader, plain old JSONObject as ususal

I’ve managed to do this with also Converter now. I think this is better solution. This is error returned from server:

"Message": "Authorization has been denied for this request."

I have this class for modeling this error:

public class ModelError {
    private String Message;

    public String getMessage() {
        return Message;
    }
    public void setMessage(String Message) {
        this.Message = Message;
    }
}

And this is code for getting error message from response.errorBody():

@Override
public void onResponse(Response<MyCustomModel> response, Retrofit retrofit) {
    if (response.errorBody() != null ) {                            
        Converter<ResponseBody, ModelError> errorConverter =
        retrofit.responseConverter(ModelError.class, new Annotation[0]);
        try {
            ModelError error = errorConverter.convert(response.errorBody());
        } catch (IOException e) {
            e.printStackTrace();
        }
        // Now use error.getMessage()
    }
    ...
}

Is there a new / better solution for this? The current retrofit2 snapshot does not provide Retrofit retrofit in the onResponse Callback anymore 😦

responseConverter is now responseBodyConverter

Update: Working for retrofit2

if (response.isSuccess()) {
    // everything ok
} else {
    Converter<ResponseBody, ErrorResponse> converter = mApp.getRetrofit().responseBodyConverter(ErrorResponse.class, new Annotation[0]);

    try {
        ErrorResponse errors = converter.convert(response.errorBody());
        Toast.makeText(this, errors.getMessage(), Toast.LENGTH_SHORT).show();
    } catch (Exception e) {
        Toast.makeText(this, R.string.error_server_error, Toast.LENGTH_LONG).show();
    }
}
Type listOfString = new TypeToken<List<String>>() {}.getType();

@meetmkjangid Strangely, if you call response.errorBody().string() twice, the second time it returns empty.

Eg:

LoggerUtils.d(AppConstants.DEBUG_TAG, "Response first- " + response.errorBody().string());
LoggerUtils.d(AppConstants.DEBUG_TAG, "Response second - " + response.errorBody().string());

**Response**

D/Log: Response before- {"status":"error","code":"ERR037","message":"Incorrect Code"}
D/Log: Response after - 

Just call .string() on it then

That’s not strange, that’s how a ResponseBody works. It’s a resource you read.

On Mon, Oct 3, 2016, 6:46 PM RmK notifications@github.com wrote:

@meetmkjangid https://github.com/meetmkjangid Strangely, if you call response.errorBody().string() twice, (one inside log and one for parsing the data), the second time it returns empty.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/square/retrofit/issues/1321#issuecomment-251159005, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEEESSDyOHC-y_GeoX5H5ZEztb_y5N0ks5qwTF8gaJpZM4GpCxz .

I have found this solution, i am not sure if it good solution. It converts errorBody to String:

BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
try {
    reader = new BufferedReader(new InputStreamReader(response.errorBody().byteStream()));
    String line;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
 } catch (IOException e) {
       e.printStackTrace();
 }

String finallyError = sb.toString();

Convert response.errorBody().string() to an array of your custom model. Use Gson or any other (de)serialization library for the conversion.

Share the StackOverflow link, I will provide the sample code.

Thanks @JakeWharton . My understanding was that it could be read any number of times. I guess that’s not possible.