kapso
kapso

Reputation: 11903

Restrofit deserializing JSON response

I have an auth REST api that returns the following JSON response (I am following http://jsonapi.org convention)

{ "user" : { "id" : 1, "first_name" : "Jack" } }

I noticed that Retrofit/Gson does not parse out the root user object automagically? so instead of giving a User object in my success callback, I am doing the following, was wondering if theres a better way to do this? I am new to Retrofit/Android.

authService.signIn(authJson, new Callback<JsonObject>() {
    @Override
    public void success(JsonObject jsonObject, Response response) {
        User user = new Gson().fromJson(jsonObject.get("user"), User.class);
        progress.hide();
        signInSuccess(user);
    }

    @Override
    public void failure(RetrofitError retrofitError) {
    }
});

Upvotes: 0

Views: 1053

Answers (2)

Nikola Despotoski
Nikola Despotoski

Reputation: 50578

You can write your own deserializer, register it in GsonBuilder and pass it to the RestAdapter

Registering Type:

            GsonBuilder gb = new GsonBuilder();
            gb.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
            gb.registerTypeAdapter(User.class, new UserDeserializerDeserializer());
            OkClient okClient = new OkClient();     
            Builder restAdapter = new RestAdapter.Builder();
            restAdapter.setEndpoint(BASE_URL);
            restAdapter.setExecutors(Executors.newCachedThreadPool(), new MainThreadExecutor());
            restAdapter.setConverter(new GsonConverter(gb.create()));
            mRestAdapter = restAdapter.build();//

UserDeserializer class:

public class UserDeserializer implements JsonDeserializer<User>{
    private static Gson sGson = new Gson();
    @Override
    public User deserialize(JsonElement arg0, Type arg1,
            JsonDeserializationContext arg2) throws JsonParseException {
       JsonObject userObject = arg0.getAsJsonObject().getAsJsonObject("user");
       return sGson.fromJson(userObject, arg1);

}

You are deserializing the response in the success method, which could hang the UI (under assumption you are using MainThreadExecutor for callbacks) in the cases where you have huge huge response.

Approach with writing your own deserializer will parse the response on the background thread too.

Upvotes: 1

Hassan Ibraheem
Hassan Ibraheem

Reputation: 2379

I think you should just create a wrapping class like that:

class UserWrapper {
      User user;
}

and make that the return type of the Retrofit interface.

There's an issue with your solution as well. If I remember correctly, Retrofit streams the network data directly to Gson on the fly. Your solution, on the other hand, will parse User object after the full response is received, and on the main thread as well.

The penalty may not be that significant for a single request, but it's something you'd probably want to avoid for general optimization.

Upvotes: 2

Related Questions