Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

De-serializing nested, generic class with gson

Using Gson, I'm trying to de-serialize a a nested, generic class. The class structure looks like the following:

Wrapper object, simplified, but normally holds other properties such as statusMessage, which are returned along with the data-field from the server:

public class Response<T> {

   private List<T> data = null;

   public List<T> getData() { return this.data; }   

}

Simple class, the expected output from data-field above (though as an array):

public class Language {
   public String alias;
   public String label;
}

Usage:

Type type = new TypeToken<Response<Language>>() {}.getType();
Response<Language> response = new Gson().fromJson(json, type);
List<Language> languages = response.getData();
Language l = languages.get(0);
System.out.println(l.alias); // Error occurs here

Where the json-variable is something like this.

However, when doing this, I recieve the following exception (on line 3, last code example):

ClassCastException: com.google.gson.internal.StringMap cannot be cast to book.Language

The exception ONLY occurs when storing the data from getData() into a variable (or when used as one).

Any help would be highly appreciated.

like image 889
Zar Avatar asked Jan 23 '13 14:01

Zar


1 Answers

The problem you're actually having is not directly due to Gson, it's because of how arrays and Generics play together.

You'll find that you can't actually do new T[10] in a class like yours. see: How to create a generic array in Java?

You basically have two options:

  1. Write a custom deserializer and construct the T[] array there as shown in the SO question I linked above
  2. Use a List<T> instead, then it will simply work. If you really need to return an array, you can always just call List.toArray() in your method.

Edited from comments below:

This is a fully working example:

public class App 
{
    public static void main( String[] args )
    {
        String json = "{\"data\": [{\"alias\": \"be\",\"label\": \"vitryska\"},{\"alias\": \"vi\",\"label\": \"vietnamesiska\"},{\"alias\": \"hu\",\"label\": \"ungerska\"},{\"alias\": \"uk\",\"label\": \"ukrainska\"}]}";
        Type type = new TypeToken<Response<Language>>(){}.getType();
        Response<Language> resp = new Gson().fromJson(json, type);

        Language l = resp.getData().get(0);
        System.out.println(l.alias);

    }
}

class Response<T> {

   private List<T> data = null;

   public List<T> getData() { return this.data; }   

}

class Language {
   public String alias;
   public String label;
}

Output:

be

like image 54
Brian Roach Avatar answered Sep 24 '22 15:09

Brian Roach