Reputation: 10948
Note : This can be achieved easily by creating 2 different GSON models, but i'm looking for a workaround.
I have a model that work with multiple JSON responses. However there is a response :
items: [
{
kind: "youtube#playlistItem",
etag: ""fpJ9onbY0Rl_LqYLG6rOCJ9h9N8/jqbcTLu8tYm8b1FXGO14gNZrFG4"",
id: "PLUQ7I1jJqKB4lJarGcpWsP62l7iC06IkE2LDE0BxLe18",
That conflict with this one (notice the same id
field with different type. The above id
is String
, the other is a Class
) :
items: [
{
kind: "youtube#searchResult",
etag: ""fpJ9onbY0Rl_LqYLG6rOCJ9h9N8/hDIU49vmD5aPhKUN5Yz9gtljG9A"",
id: {
kind: "youtube#playlist",
playlistId: "PLh6xqIvLQJSf3ynKVEc1axUb1dQwvGWfO"
},
Is it possible to just use a single GSON model that can read both responses?
Thanks a lot for your time
UPDATE
This is inside my Model
, i changed the id
variable from String
to a Class
:
private Id id;
public class Id
{
private String id;
private String kind;
private String playlistId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public String getPlaylistId() {
return playlistId;
}
public void setPlaylistId(String playlistId) {
this.playlistId = playlistId;
}
}
This is how i do the request :
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Response.class,
new JsonDeserializer<Item.Id>() {
@Override
public Item.Id deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
if(jsonElement.isJsonObject())
{
result.setKind(jsonElement.getAsJsonObject().get("kind").getAsString());
result.setPlaylistId(jsonElement.getAsJsonObject().get("playlistId").getAsString());
//return new Item.Id(jsonElement.getAsJsonObject().get("kind").getAsString(), jsonElement.getAsJsonObject().get("playlistId").getAsString());
return result;
}
else
{
result.setId(jsonElement.getAsString());
//return new Item.Id(jsonElement.getAsString());
return result;
}
}
});
Upvotes: 0
Views: 802
Reputation: 1853
The problem
You can only have id represent single type of variable, in this case on the first response you've got string, and on second case you've got an object, which has a "kind" and a "playlistId"
This seems like a weird design on backend side, but it probably isn't under your control
Solution
What you can do is if you think that the id in the first, and second responses are of same type you could create an encapsulating class that would contain these fields like
class Id {
private String stringId;
private String kind;
private String playlistId;
}
and create a custom JsonDeserializer that would based on the type of the JSON response create a corresponding Id object in following fashion:
new JsonDeserializer<Id>() {
@Override
public Id deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if(json.isJsonObject()) {
return new Id(json.getAsJsonObject().get("kind").getAsString(), json.getAsJsonObject().get("playlistId").getAsString());
} else {
return new Id(json.getAsString());
}
}
}
and register it on your gson object, so it would handle the deserialization of Id fields, and depending of its type base its creation
Or then you could create a deserializer that would deserialize the containing object and use different fields based on the type of id, but you should get the idea!
You can register your JsonDeserializer on gson using GsonBuilder and in GsonBuilder calling registerTypeAdapter with the type you're registering type adapter on and with the typeadapter you want to use in the following way:
return new GsonBuilder().registerTypeAdapter(Id.class, new JsonDeserializer<Id>() {
//..
}).build();
You can read more about custom typeAdapters in gson documentation, here!
Upvotes: 2