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