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"
}
}
CodePudding user response:
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