Reputation: 908
I am trying to resolve a problem I have when deserializing a HashMap<Integer, MyParcelablePojo>
. Trying to find an answer, I found these questions:
If I try with:
HashMap<Integer, MyParcelablePojo> mHashMap = new Gson().fromJson(the_json_string, HashMap.class);
...the resulting HashMap
contains LinkedTreeMap
objects instead of MyParcelablePojo
objects.
Due to this, I tried to use a TypeToken
in a similar way than I saw in the second question linked above, but it doesn't let me to specify the parameters of HashMap
. If I try:
// XXX I am not sure if this "Type" is the correct one
// there were several "Type" classes to choose from
import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken;
Type collection_type = new TypeToken<HashMap<Integer, MyParcelablePojo>>();
...Android Studio shows me this error:
'TypeToken()' has protected access in 'com.google.gson.reflect.TypeToken'
...just for sticking to the example I saw, I tried with new TypeToken<HashMap<T>>
to see if the error dissapeared (just for curiosity, I'm not interested in using generic T
for this at all), and then it said "cannot resolve T", which is too weird... but this is irrelevant for my problem, I just added it for the sake of completeness...
...going back to the point, so TypeToken
's constructor is protected, right? So, extending the class might help, right? But if I see the constructor, it is just too weird for me to understand. Parametrized types are very weird to use this way (at least for my current understanding of them). The part <? super T>
is a little confusing (looks like it is invoking the parent type of T
, but I just don't fully get it). But, even more weird for me, is $Gson$Types.getRawType(type)
... I wonder what are those $
used for...:
protected TypeToken() {
this.type = getSuperclassTypeParameter(getClass());
this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
this.hashCode = type.hashCode();
}
I just want to avoid that Gson.fromJson
method returns LinkedTreeMap
as values, instead of MyParcelablePojo
. The answers provided in the questions linked seem too generic for me, so I don't understand how to apply them to my case (please notice that I am not interested in genericity for now). I even doubt they might be applicable to my case.
The main motive I am using HashMap is because I want to define indexes myself, using an ID basis. What should I do to resolve this issue of deserializing from a JSON string properly?
Upvotes: 1
Views: 10302
Reputation: 3104
If you are using kotlin don't forget to use object:
val type: Type = object : TypeToken<ArrayList<YourArrayType>>() {}.type
Upvotes: 2
Reputation: 555
I don't think you've used the TypeToken properly, I've been doing;
HashMap<Integer, GenericObject> mHashMap = new Gson().fromJson(json, new TypeToken<HashMap<Integer, GenericObject>>(){}.getType());
Where you pass the type, not the actual token.
Upvotes: 1
Reputation: 8231
You instantiate a TypeToken
via creating a subclass, which is usually anonymous:
Type collection_type = new TypeToken<HashMap<Integer, MyParcelablePojo>>(){}.getType();
Note the {}
in my answer. The reason for this is explained in the JavaDoc:
/**
* Represents a generic type {@code T}. Java doesn't yet provide a way to
* represent generic types, so this class does. Forces clients to create a
* subclass of this class which enables retrieval the type information even at
* runtime.
*
* <p>For example, to create a type literal for {@code List<String>}, you can
* create an empty anonymous inner class:
*
* <p>
* {@code TypeToken<List<String>> list = new TypeToken<List<String>>() {};}
*
* <p>This syntax cannot be used to create type literals that have wildcard
* parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}.
*
* @author Bob Lee
* @author Sven Mawson
* @author Jesse Wilson
*/
Upvotes: 10