Last active
April 21, 2016 04:31
-
-
Save VallaDanger/268bd0e7c5e5d5ee7ea78f130f7b8259 to your computer and use it in GitHub Desktop.
GSON JsonArray to Guava ImmutableList
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static void main(String[] args) { | |
Type type = getCollectionType(ImmutableList.class, Number.class); | |
Gson gson = new GsonBuilder().registerTypeAdapter(type, new ImmutableList_TypeAdapter<Number>()).create(); | |
ImmutableList<Number> list = gson.fromJson("[1,2,3]", type); | |
ListVO vo = gson.fromJson("{\"numbers\":[1,2,3]}", ListVO.class); | |
} | |
private static class ListVO { | |
@Expose @SerializedName("numbers") | |
ImmutableList<Number> numbers; | |
public ImmutableList<Number> getNumbers() { | |
return this.numbers; | |
} | |
} | |
private static <V, C extends Collection<V>> Type getCollectionType(Class<C> collectionType, Class<V> elementsType) { | |
return new TypeToken<Collection<V>>() {} | |
.where(new TypeParameter<V>() {}, elementsType) | |
.getSubtype(collectionType).getType(); | |
} | |
private static class ImmutableList_TypeAdapter implements JsonDeserializer<ImmutableList<Number>> { | |
public ImmutableList<Number> deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException { | |
if(!jsonElement.isJsonArray()) { | |
return ImmutableList.of(); | |
} | |
ImmutableList.Builder<Number> list = ImmutableList.builder(); | |
for(JsonElement element : jsonElement.getAsJsonArray()) { | |
JsonPrimitive primitive; | |
if(element.isJsonPrimitive() && (primitive = element.getAsJsonPrimitive()).isNumber()) { | |
list.add(primitive.getAsNumber()); | |
} | |
} | |
return list.build(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
very simple example on how to deserialize a GSON's
JsonArray
into a Guava ImmutableList, it could be easily modified to support any type of instance that implements java.util.Collection (such asImmutableList
>List
>Collection
).Guava code makes use of static factories to create instances which effectively hides implementations from the user (interface driven APIs, constructors always create instances of a type but methods can create and return instances of any subtype). Guava's
ImmutableList
is no exception to the rule and so it is non instantiable (abstract class) and GSON has no default adapter for such type, in fact if you attempt to deserialize a JSON array into an ImmutableList (even when it implementsjava.util.List
, also non instantiable but effectively managed by GSON) you get anInstantiationException
(unchecked exception).An instance of ImmutableList is easy to create by calling ImmutableList#copyOf, but if you know in advance that your object is never going to change, why create defensive copies every time when you can simply deserialize into one.
In this example you'd only need a
TypeAdapter
, but what if you wanted another implementation or what if you need an instance ofImmutableList<MyVeryOwnObject>
without having to create an annotated object to hold it and you'd also want to implement some sort of type safety, etc... That's why I also provided a way to define a method to get a Type for aCollection
to inform GSON exactly what it is working with.While this is a very simple example, an experienced developer can make use of the polymorphic characteristics of the language to make it as robust as you may need. Think of a CollectionTypeFactory using guice
AssistedInject
.remember do not abuse of conditionals !!