Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserializing Generic Types with GSON

I have some problems with implementation of Json Deserialization in my Android application (with Gson library)

I've made class like this

public class MyJson<T>{     public List<T> posts; } 

And Deserialization call is:

public class JsonDownloader<T> extends AsyncTask<Void, Void, MyJson<T>> { ... protected MyJson<T> doInBackground(Void... params) {   ...     Reader reader = new InputStreamReader(content);     GsonBuilder gson = new GsonBuilder();     Type collectionType = new TypeToken<MyJson<T>>() {}.getType();     result = gson.create().fromJson(reader, collectionType);   ...   } } 

Problem is that result.posts list after call holds one Array of LinkedTreeMap Objects(with correct values so problem is Deserialization) instead of MyJson Objects. When I use MyObject instead of T everything is running fine and MyObject is correct.

So is there any way to implement deserialization call without creating custom deserializer?

like image 659
VizGhar Avatar asked Aug 23 '13 07:08

VizGhar


People also ask

How do I deserialize JSON with Gson?

Deserialization – Read JSON using Gson. Deserialization in the context of Gson means converting a JSON string to an equivalent Java object. In order to do the deserialization, we need a Gson object and call the function fromJson() and pass two parameters i.e. JSON string and expected java type after parsing is finished ...

Does Gson ignore extra fields?

3. Deserialize JSON With Extra Unknown Fields to Object. As you can see, Gson will ignore the unknown fields and simply match the fields that it's able to.

Does Gson require empty constructor?

Gson will not work on objects with recursive references. Gson requires the class to have a default no-args constructor. If the no-args constructor is not provided, we can register an InstanceCreator with Gson, allowing us to deserialize instances of classes.

What is TypeToken Gson?

protected TypeToken() Constructs a new type literal. Derives represented class from type parameter. Clients create an empty anonymous subclass.


2 Answers

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 required MyJson<MyObject> myJson = doInBackground(MyObject.class); 
like image 103
Ravi K Thapliyal Avatar answered Sep 28 '22 05:09

Ravi K Thapliyal


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)

like image 29
John B Avatar answered Sep 28 '22 06:09

John B