Chris
Chris

Reputation: 11

How to parse JSON arrays with retrofit

So I have a retrofit interface:

public interface RestUserInformation {
    @GET("/api/me")
    void getInfo(Callback<UserInformation> callback);
}

A RestAdapter:

RestAdapter userInformation = newRestAdapter.Builder()
                              .setEndpoint(IP_ADDRESS)
                              .setRequestInterceptor(requestInterceptor)
                              .build();

Which make API calls and receive a JSON body answer like:

{"user":{ 
     "id":50,
     "email":"[email protected]",
     "first_name":"chris",
     "last_name":"cr",
     "birthdate":"1817-03-04",
     "gender":1,
     "country":"fr"
     {     
     "id":8,
     "language":"Spanish",
     "flag_path":"public/images/flags/Argentina.ico",
     "created_at":"2014-11-05T20:42:39.294Z",
     "updated_at":"2014-11-05T20:42:39.294Z",
     "name":"Argentina","available":false,
     "i18n_key":null
     }
    }
}

And I'd like to parse it and fill a class with it, so I created the class UserInformation.java:

public class UserInformation {
    int id;
    String email;
    String first_name;
    String last_name;
    String birthdate;
    int gender;
    String country;  }

I've been trying to do this using the callback function:

        RestUserInformation getUserInfo = userInformation.create(RestUserInformation.class);
        getUserInfo.getInfo(new Callback<UserInformation>() {
               @Override
               public void success(UserInformation user, Response response) {
                                            }

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

I have tried many things but it doesn't work and the attribute of the UserInformation class stay empty.. Any ideas about how to do it?

Upvotes: 1

Views: 1417

Answers (2)

Bryan Herbst
Bryan Herbst

Reputation: 67259

By default, Retrofit uses GSON to parse JSON.

GSON attempts to map your JSON fields to your Java objects using a 1:1 mapping- that is the structure of the Java class must match the structure of the JSON to perform automatic parsing.

The problem here is that your JSON isn't a single object- it is an object (labeled "user") within another object.

To solve this, you can either create another class to encapsulate the outer object or you can create a custom deserializer for GSON.

Example of a wrapper class for the outer object:

public class UserResponse {
    public UserInformation user;
}

Here's an example of a custom deserializer, if you want to go down that route:

public class UserInformationAdapter implements JsonDeserializer<UserInformation> {
    @Override
    public UserInformation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        // Get the root JSON object
        JsonObject rootObject = json.getAsJsonObject();

        // Get the user JSON element
        JsonElement userElement = rootObject.get("user");

        // Let GSON try to automatically deserialize the user element.
        return context.deserialize(userElement, UserInformation.class);
    }
}

You can register this type adapter in Retrofit like so:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(UserInformation.class, new UserInformationAdapter());
Gson gson = gsonBuilder.create();
RestAdapter adapter = new RestAdapter.Builder()
    .setConverter(new GsonConverter(gson))
    .build();

This way instead of trying to use its default parsing strategy, GSON will use your UserInformationAdapter to deserialize the JSON.

Upvotes: 5

Mateus Brandao
Mateus Brandao

Reputation: 900

You have to anotate the fields with the @SerializedName passing the respective json property, so that Retrofit can parse the JSON to your Object Try this:

public class UserInformation implements Serializable {
        @SerializedName("id")
        int id;
        @SerializedName("email")
        String email;
        @SerializedName("first_name")
        String first_name;
        @SerializedName("last_name")
        String last_name;
        @SerializedName("birthdate")
        String birthdate;
        @SerializedName("gender")
        int gender;
        @SerializedName("country")
        String country;  
}

Upvotes: -2

Related Questions