Jo Colina
Jo Colina

Reputation: 1924

Java Gson Incompatible Types

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

Answers (1)

JHH
JHH

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

Related Questions