9

Retrofit version: 2.1.0
OkHttp version: 3.4.1

In the onResponse method of my Retrofit Callback implementation, I have the following logic:

@Override
public void onResponse(Call<BaseResponseBody<T>> call, Response<BaseResponseBody<T>> response) {
  if (response != null && response.isSuccessful() && response.body() != null && response.body().containsValidSuccess()) {
    // Perform actions using response.body().getValue().
  } else {
    // If containsValidSuccess returns false, show a dialog that includes the raw JSON response body.
  }
}

Here BaseResponseBody is my own type (not related to OkHttp's ResponseBody) that wraps a generic type T extends Validatable, where Validatable is an interface that exposes an isValid method used to confirm that deserialized responses satisfy given constraints.

If I receive a response that is ostensibly successful (HTTP code 2XX, non-null response body, etc.), but whose deserialized body does not pass this validation step (i.e. containsValidSuccess returns false), I would like to present a dialog whose message includes the raw (pre-deserialization) response body. However, I don't seem to be able to access this raw response body through the Retrofit Response type.

I have read other pages that seem to suggest an Interceptor might better suit my needs. I'm familiar with interceptors and use them for other call manipulations within my app, but I don't see exactly how I would pass information from my interceptor to the final Callback.onResponse method in order to present the dialog.

Am I on the right path? Am I missing something obvious in the Retrofit APIs? How can I achieve my stated goal? Thanks!

stkent
  • 19,772
  • 14
  • 85
  • 111
  • Have you seen this http://stackoverflow.com/questions/33282889/get-raw-http-response-with-retrofit or this http://stackoverflow.com/questions/37088975/how-to-get-raw-response-and-request-using-retrofit-2-0 – OneCricketeer Oct 27 '16 at 15:05
  • Yep! If I call `response.raw().body().string()` in my `Callback` I see the following exception: `java.lang.IllegalStateException: Cannot read raw response body of a converted body.`. On the other hand, calling `response.body()` in my `Callback` returns a Retrofit `Response` object that does not have a `string` method. – stkent Oct 27 '16 at 15:14
  • @stkent do you have custom adapter written? – Raghunandan Oct 27 '16 at 15:26
  • @Raghunandan what exactly do you mean by a custom adapter? I am using several custom type adapters when configuring my Gson instance. – stkent Oct 27 '16 at 15:27
  • @stkent custom class that extends `CallAdapter.Factory ` – Raghunandan Oct 27 '16 at 15:28
  • @stkent check this sample https://github.com/square/retrofit/blob/master/samples/src/main/java/com/example/retrofit/ErrorHandlingAdapter.java if it helps and can you post `BaseResponseBody` – Raghunandan Oct 27 '16 at 15:31
  • @Raghunandan thanks, I'll check out the call adapter stuff! How do you imagine the interceptor version would work? Return a custom Response subclass and then attempt to cast in the callback? – stkent Oct 27 '16 at 16:26
  • Did you manage to solve this? – Jumpa Apr 17 '19 at 10:33
  • @Jumpa I did not; I moved on to a different project and have not revisited this since. Does Raghunandan's suggestion help you at all? – stkent Apr 17 '19 at 13:19
  • Mh not exactly, because I've to parse error json even if the https status code is 200...https://stackoverflow.com/questions/55725736/access-raw-response-after-conversion?noredirect=1#comment98130581_55725736 – Jumpa Apr 17 '19 at 13:25

1 Answers1

1

try this

@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
 if (response != null && response.isSuccessful() && response.body() != null && response.body().containsValidSuccess()) {
   // Perform actions using response.body().getValue().
 } else {
  // If containsValidSuccess returns false, show a dialog that includes the raw JSON response body.
 }
}

after then you can put it to your POJO like this

Gson g= new Gson(); 
POJOClass pojo=g.fromJson(response.body,POJOClass.class);
Vishal Sanghani
  • 874
  • 1
  • 10
  • 19
  • Doing this would require that I manually apply Gson conversion to my `JsonObject` ; I'd rather continue to leverage the built in adapter mechanism for that if possible. – stkent Oct 27 '16 at 15:15
  • get you will get json format in raw format after then you can put it to your POJO like this Gson g= new Gson(); POJOClass pojo=g.fromJson(response.body,POJOClass.class); – Vishal Sanghani Oct 27 '16 at 15:20
  • Then I lose the generic nature of the Callback, which is a grim side-effect. – stkent Oct 27 '16 at 15:24