Reputation: 661
So, I'm working right now on trying to figure out how to parse a large number of different JSON objects without having to hard-code functions to serialize and deserialize each of the objects. I started using Gson, and that has been working pretty well. A problem begins to appear though when I am trying to use a list of objects.
I would like to create a function that will work with any of my data model objects that I can pass a JSONArray and the class type that the JSON contains, so that I would have a call that looks something like this -
response = JSONHelper.createObjectList(jsonArray, DataObject.class);
Btw, I'm not posting from my dev machine, so forgive me if there are a few typos in my code.
I tried to create that effect by writing something like this (inside my JSONHelper class) -
public List createObjectList(JSONArray jsonArray, Class type) {
Gson gson = new Gson();
Type listType = new TypeToken<List<type>>() {}.getType();
List<type> data = gson.fromJson(jsonArray, listType);
return data;
}
Okay, so obviously that isn't working code, but that is kinda how I wanted to be able to get this to work. I tried several different ways and variations, but I haven't been able to figure out anything that works really nicely.
I am new to the Android/Java world, so i'm still learning the in's and out's of the language. If someone could give me some tips on how I could achieve what I am looking for, it would be very helpful. Thanks.
Upvotes: 0
Views: 218
Reputation: 76908
The answer is: You can't do what you're trying to do in Java because of type erasure.
That's the reason you have to use TypeToken
and pass a Type
to Gson's fromJson()
method; the type information for T
isn't available at runtime. Generics in Java are for the most part just compile time type checking.
Ideally you'd like to be able to do this:
public <T> List<T> createList(JsonArray a, Class<T> clazz)
{
Type t = new TypeToken<List<T>>(){}.getType();
return new Gson().fromJson(a, t);
}
But you can't, because T gets erased. If you try this you'll find the result completely confusing; you get a List
back, but it won't actually contain your class and throw a cast exception.
Effectively, your method would have to look like this:
public <T> List<T> createList(JsonArray a, Type t)
{
List<T> list = new Gson().fromJson(a, t);
return list;
}
Which of course would be silly since you're now calling a method you wrote instead of just calling the method in Gson.
Edit to add:
Thinking about it, there's way around this for List
types. You can use arrays:
public <T> List<T> createList(JsonArray a, Class<T[]> c)
{
T[] array = new Gson().fromJson(a, c);
return Arrays.asList(array);
}
Because you're not trying to rely on the generic type from inside a List
and instead are passing an array type for the class... it works. A bit messy, but it works:
List<MyPojo> list = createList(a, MyPojo[].class);
Upvotes: 2