Deserializing Generic Types with GSON
You have to specify the type of T
at the time of deserialization. How would your List
of posts
get created if Gson
didn't know what Type
to instantiate? It can't stay T
forever. So, you would provide the type T
as a Class
parameter.
Now assuming, the type of posts
was String
you would deserialize MyJson<String>
as (I've also added a String json
parameter for simplicity; you would read from your reader
as before):
doInBackground(String.class, "{posts: [\"article 1\", \"article 2\"]}");protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) { GsonBuilder gson = new GsonBuilder(); Type collectionType = new TypeToken<MyJson<T>>(){}.getType(); MyJson<T> myJson = gson.create().fromJson(json, collectionType); System.out.println(myJson.getPosts()); // ["article 1", "article 2"] return myJson;}
Similarly, to deserialize a MyJson
of Boolean
objects
doInBackground(Boolean.class, "{posts: [true, false]}");protected MyJson<T> doInBackground(Class<T> type, String json, Void... params) { GsonBuilder gson = new GsonBuilder(); Type collectionType = new TypeToken<MyJson<T>>(){}.getType(); MyJson<T> myJson = gson.create().fromJson(json, collectionType); System.out.println(myJson.getPosts()); // [true, false] return myJson;}
I've assumed MyJson<T>
for my examples to be as
public class MyJson<T> { public List<T> posts; public List<T> getPosts() { return posts; }}
So, if you were looking for to deserialize a List<MyObject>
you would invoke the method as
// assuming no Void parameters were requiredMyJson<MyObject> myJson = doInBackground(MyObject.class);
Have you tried?
gson.create().fromJson(reader, MyJson.class);
EDIT
After reading this post it seems that you use of Type
is correct. I believe your issue is the use of T
. You must remember that with Java there is type-erasure. This means that at runtime all instances of T
are replaced with Object
. Therefore at runtime what you are passing GSON is really MyJson<Object>
. If you tried this with a concrete class in place of <T>
I believe it would work.
Google Gson - deserialize list<class> object? (generic type)
So the above answer didn't work for me, after trial and error that's how my code ended:
public class AbstractListResponse<T> { private List<T> result; public List<T> getResult() { return this.result; }}
The important part here is the method signature, including the '< T >' on the left.
protected <T> AbstractListResponse<T> parseAbstractResponse(String json, TypeToken type) { return new GsonBuilder() .create() .fromJson(json, type.getType());}
When calling Gson, the method receives the TypeToken of the generic object.
TypeToken<AbstractListResponse<MyDTO>> typeToken = new TypeToken<AbstractListResponse<MyDTO>>() {};AbstractListResponse<MyDTO> responseBase = parseAbstractResponse(json, typeToken);
And finally the TypeToken can use MyDTO, or even a simple object, just MyDTO.