I want to convert a class which contains a Hashmap of non-primitive keys or values to Json using Gson.
so I realize that Hashmap keys and values are stored only as Strings when serializing with Gson. so I can’t serialize them. I ran into this solution which should be fine, but I get this error:
java: cannot find symbol symbol: class TypeAdapterRuntimeTypeWrapper location: class TypeAdapters.MapTypeAdapterFactory.Adapter<K,V>
any idea?
EDIT:
this is my code:
public class App { public static void main(String[] args) throws Exception { Gson gson = new GsonBuilder().setPrettyPrinting().create(); GameController gameController = new GameController(); System.out.println(gson.toJson(gameController)); } } class GameController { HashMap<Tile, TileState> map = new HashMap<>(); public GameController() { map.put(new Tile(), TileState.VISIBLE); map.put(new Tile(), TileState.REVEALED); } } class Tile { @Override public int hashCode() { return super.hashCode(); } } enum TileState { REVEALED, VISIBLE }
and the output is:
{ "map": { "dir.Tile@6996db8": "REVEALED", "dir.Tile@368102c8": "VISIBLE" } }
Advertisement
Answer
I ran into this solution which should be fine, but I get this error:
java: cannot find symbol symbol: class TypeAdapterRuntimeTypeWrapper location: class TypeAdapters.MapTypeAdapterFactory.Adapter<K,V>any idea?
MapTypeAdapterFactory
is an internal Gson class; you should not copy its source to your project because:
- In case bugs are found in that class and fixed in the Gson project, your copy would still contain those bugs
- This internal class itself depends on other internal classes, in this case
TypeAdapterRuntimeTypeWrapper
, which is why you are seeing this compilation error
Instead, try to use the functionality Gson provides out-of-the-box. The User Guide explains how Map
serialization works and how you can customize it. Unfortunately due to legacy reasons Gson uses toString()
for serialization. There are a few possible solutions:
- Override
toString()
to return a more reasonable representation, and register aTypeAdapter
which handles deserialization - Only register a
TypeAdapter
which handles both serialization and deserialization, and useGsonBuilder.enableComplexMapKeySerialization()
- Only use
GsonBuilder.enableComplexMapKeySerialization()
. In that case Gson will use reflection to serialize and deserializeTile
instances
Also, as side note: Your Tile
class looks a bit incorrect:
- Normally when using a class as key of a
Map
you overrideequals
andhashCode
; otherwise instances are compared by reference equality only, and separate instances with the same field values are not considered equal - When overriding
hashCode()
you normally also overrideequals(Object)
- Just calling
super.hashCode()
in yourhashCode()
implementation has no special effect and behaves the same way as if you had not overridden the method