6

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.

Community
  • 1
  • 1
Zar
  • 6,272
  • 6
  • 49
  • 74

1 Answers1

8

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

Community
  • 1
  • 1
Brian Roach
  • 72,790
  • 10
  • 128
  • 154
  • Had no idea that the problem lied with the generic-array part. I'm pretty new to both Java and generics, though. Anyways, your answer was exatly what I was looking for - I went with the `List` solution. Many, many thanks; you made my night! :-) – Zar Jan 23 '13 at 21:45
  • Hmm, upon further testing, it doesn't work as good as I hoped. doing `Language l = languages.get(0); /* from map */` and then `println(l.alias)` yields this exception: http://pastebin.com/Wctziipr . Any ideas or suggestions would be appreciated! – Zar Jan 23 '13 at 22:00
  • Can you edit your question with your updated class and code? I didn't test it but it really should work. – Brian Roach Jan 23 '13 at 22:10
  • Hehe, if I had a cent for every time I've said that. Question updated. – Zar Jan 23 '13 at 22:22
  • See edit - what version of Gson are you using? This is tested with 2.2.2 – Brian Roach Jan 23 '13 at 22:24
  • Ha .. and actually ... it works fine in 2.2.2 with `T[]` - I dont think that used to work. You're still better off using `List` though. – Brian Roach Jan 23 '13 at 22:33
  • 2.2.2 here aswell. Tested a bit more, works fine now. Thanks once again! However, in reality, I'm actually calling another classes method which creates the `Response` object. Such as: http://pastebin.com/1WsTCdAi This doesn't work, though. If you have some time, do you have any suggestions? – Zar Jan 23 '13 at 22:36
  • Not without a bit more code/context ... it sounds like you've got something really odd going on with the Types. You might want to repost as a new question. Narrow it down to a complete example that demonstrates the error. – Brian Roach Jan 23 '13 at 22:46
  • Will do. Thanks a lot for all your time, it's appreciated! – Zar Jan 23 '13 at 22:50
  • No worries - glad to help. – Brian Roach Jan 23 '13 at 22:53