4

I use Retrofit 2.0.0-beta2.

I found an example of a synchronous conversion .errorBody to object.

I need to implement it asynchronously.

It's my json:

{
  "error_msg": "This user name is already registered."
}

When run the asynchronous example, I get null.

package com.test.client;

import com.squareup.okhttp.ResponseBody;

import java.io.IOException;
import java.lang.annotation.Annotation;

import retrofit.Call;
import retrofit.Callback;
import retrofit.Converter;
import retrofit.GsonConverterFactory;
import retrofit.Response;
import retrofit.Retrofit;
import retrofit.http.GET;

public final class DeserializeErrorBody {

interface Service {
    @GET("account.signup")
    Call<User> getUser();
}

static class User {
    // normal fields...
}

static class Error {
    String error_msg;
}

public static void main(String... args) throws IOException {
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.site.com/method/")
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    Service service = retrofit.create(Service.class);


    // ASYNCHRONOUS

    Call<User> response = service.getUser();
    response.enqueue(new Callback<User>() {

        @Override
        public void onResponse(Response<User> response, Retrofit retrofit) {
            if(!responce.isSuccess()) {

                System.out.println(response.errorBody().string()); // returns { "error_msg": "This user name is already registered."}    :)))))

                Converter<ResponseBody, Error> errorConverter = retrofit.responseConverter(Error.class, new Annotation[0]);

                try {
                    Error error = errorConverter.convert(response.errorBody());

                    System.out.println(error); // returns null   :((((((

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Throwable t) {
            // ...
        }
    });


    // SYNCHRONOUS

    /*
    Response<User> call = service.getUser().execute();
    Converter<ResponseBody, Error> errorConverter = retrofit.responseConverter(Error.class, new Annotation[0]);

    Error error = errorConverter.convert(call.errorBody());
    System.out.println(error); // returns Object     :))))))
    System.out.println(error.error_msg); // returns "This user name is already registered."    :))))))
    */

}
}

Sorry for my bad English :)

In asynchronous request successfully returns a string. However, conversion to the object is not running.

How to get the object instead of null?

Qulery
  • 193
  • 4
  • 13
  • What is your question? – Jason D Oct 07 '15 at 16:04
  • How to get the object instead of null? – Qulery Oct 07 '15 at 16:08
  • 1
    Your method **Call getUser();** is synchronous for asynchronous request check [this](https://futurestud.io/blog/retrofit-synchronous-and-asynchronous-requests/) link – NullPointerException Oct 07 '15 at 16:44
  • @NullPointerException, Your article uses version **retrofit 1.9**. In version **2.0**, the interface is described by the same for synchronous and asynchronous requests. http://inthecheesefactory.com/blog/retrofit-2.0 – Qulery Oct 07 '15 at 16:50

1 Answers1

4

Ok, so your problem lies within following line of code:

System.out.println(response.errorBody().string());

If you take a look on the source of com.squareapp.okhttp.ResponseBody you will find out that call to string() will consume out the stream of response. So the next time you are trying to parse body of response

Error error = errorConverter.convert(response.errorBody());

Call to errorBody() will give no stream of bytes and Gson won't parse any data back.

So what should you try? Just don't consume errorBody() in the way you did. Simply remove this line:

System.out.println(response.errorBody().string());

If you need advanced logging follow link. This should essentially look like this:

OkHttpClient client = new OkHttpClient();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(Level.BASIC);
client.interceptors().add(logging);

Retrofit retrofit = new Retrofit.Builder()
       .baseUrl("https://api.site.com/method/")
       .addConverterFactory(GsonConverterFactory.create())
       .client(client)
       .build();
Tom Koptel
  • 309
  • 1
  • 9
  • Thank you very much! Everything is working! Thanks for the help!! – Qulery Oct 07 '15 at 17:42
  • I am having a similar issue, can somebody please advise? http://stackoverflow.com/questions/39261481/assigning-reference-when-accessing-json-response – tccpg288 Sep 01 '16 at 01:57