Reputation: 1924
I'm using Gson to encode and decode POJOs to JSON, however, Gson has some unexpected behaviour.
As a matter of fact, I have an object that looks like this
public class MyClass{
public int id;
public Object someData;
}
And it's constructor with id
and data
.
I often pass a HashMap<Integer, Integer>
to Object, which Gson is parsing quite perfectly. The problem is the decoding, it decodes it as a hashmap of Integer,Double
even though I called the function like so:
private HashMap<Integer, Integer> hashMapTemplate = new HashMap<>();
HashMap<Integer, Integer> myData = gson.fromJson(data, hashMapTemplate.getClass());
And I then manipulate myData, which throws a
ClassCastException: java.lang.Double cannot be cast to java.lang.Integer.
And if I add an explicit cast (int)
it throws a
ClassCastException: java.lang.String cannot be cast to java.lang.Integer.
What I don't understand is how a HashMap defined to hold two integers can hold wether a Double or a String...
Does anyone have a solution? thanks!
Upvotes: 1
Views: 700
Reputation: 9315
Due to type erasure, the class object for a HashMap
is the same regardless of whether it's a HashMap<String, Integer>
or HashMap<Foo, Bar>
. In fact, your current code might as well have passed HashMap.class
to fromJson
and skipped the template object altogether.
To preserve generic types, you instead need a TypeToken
:
HashMap<Integer, Integer> h = gson.fromJson(json, new TypeToken<HashMap<Integer, Integer>>() {});
TypeToken uses a clever trick, utilizing Class.getGenericSuperclass()
,and for that reason it must always be created as a subclass, hence the inline anonymous subclassing syntax.
Upvotes: 3