Reputation: 11903
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
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
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