I have some odd JSON like:
[
{
"type":"0",
"value":"my string"
},
{
"type":"1",
"value":42
},
{
"type":"2",
"value": {
}
}
]
Based on some field, the object in the array is a certain type. Using Gson, my thought is to have a TypeAdapterFactory that sends delegate adapters for those certain types to a TypeAdapter, but I'm hung up on understanding a good way of reading that "type" field to know which type to create. In the TypeAdapter,
Object read(JsonReader in) throws IOException {
String type = in.nextString();
switch (type) {
// delegate to creating certain types.
}
}
would assume the "type" field comes first in my JSON. Is there a decent way to remove that assumption?
The JsonSerializer interface looks like this: After creating custom serializer for Json, we will also need to register this serializer through GsonBuilder.registerTypeAdapter (Type, Object). Gson invokes it’s call-back method serialize () during serialization when it encounters a field of the specified type.
Welcome back to another blog post in our Gson series. After reviewing the basics of Gson, model annotations and mapping of nested objects, we'll go on to a core feature: mapping of Arrays and Lists. Almost every data model out there utilizes some form of list. Fortunately, Gson makes it really easy to deal with them.
Yes, Gson sorted the fields alphabetically again, but otherwise the result is exactly as we've expected. Gson correctly created the nested userAddress JSON object. Of course, we could add more nested objects for the user's payment method or work address. Even the nested objects can have nested objects!
Yes, Gson sorted the fields alphabetically again, but otherwise the result is exactly as we've expected. Gson correctly created the nested userAddress JSON object. Of course, we could add more nested objects for the user's payment method or work address.
Here is some code I wrote to handle an array of NewsFeedArticle and NewsFeedAd items in Json. Both items implement a marker interface NewsFeedItem to allow me to easily check if the TypeAdater should be used for a particular field.
public class NewsFeedItemTypeAdapterFactory implements TypeAdapterFactory {
@Override
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (!NewsFeedItem.class.isAssignableFrom(type.getRawType())) {
return null;
}
TypeAdapter<JsonElement> jsonElementAdapter = gson.getAdapter(JsonElement.class);
TypeAdapter<NewsFeedArticle> newsFeedArticleAdapter = gson.getDelegateAdapter(this, TypeToken.get(NewsFeedArticle.class));
TypeAdapter<NewsFeedAd> newsFeedAdAdapter = gson.getDelegateAdapter(this, TypeToken.get(NewsFeedAd.class));
return (TypeAdapter<T>) new NewsFeedItemTypeAdapter(jsonElementAdapter, newsFeedArticleAdapter, newsFeedAdAdapter).nullSafe();
}
private static class NewsFeedItemTypeAdapter extends TypeAdapter<NewsFeedItem> {
private final TypeAdapter<JsonElement> jsonElementAdapter;
private final TypeAdapter<NewsFeedArticle> newsFeedArticleAdapter;
private final TypeAdapter<NewsFeedAd> newsFeedAdAdapter;
NewsFeedItemTypeAdapter(TypeAdapter<JsonElement> jsonElementAdapter,
TypeAdapter<NewsFeedArticle> newsFeedArticleAdapter,
TypeAdapter<NewsFeedAd> newsFeedAdAdapter) {
this.jsonElementAdapter = jsonElementAdapter;
this.newsFeedArticleAdapter = newsFeedArticleAdapter;
this.newsFeedAdAdapter = newsFeedAdAdapter;
}
@Override
public void write(JsonWriter out, NewsFeedItem value) throws IOException {
if (value.getClass().isAssignableFrom(NewsFeedArticle.class)) {
newsFeedArticleAdapter.write(out, (NewsFeedArticle) value);
} else if (value.getClass().isAssignableFrom(NewsFeedAd.class)) {
newsFeedAdAdapter.write(out, (NewsFeedAd) value);
}
}
@Override
public NewsFeedItem read(JsonReader in) throws IOException {
JsonObject objectJson = jsonElementAdapter.read(in).getAsJsonObject();
if (objectJson.has("Title")) {
return newsFeedArticleAdapter.fromJsonTree(objectJson);
} else if (objectJson.has("CampaignName")) {
return newsFeedAdAdapter.fromJsonTree(objectJson);
}
return null;
}
}
}
You can then register this with Gson using the following code.
return new GsonBuilder()
.registerTypeAdapterFactory(new NewsFeedItemTypeAdapterFactory())
.create();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With