Skip to content
Advertisement

Converting a class containing a hashmap of non-primitive keys or values to Json

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:

  1. In case bugs are found in that class and fixed in the Gson project, your copy would still contain those bugs
  2. 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:

  1. Override toString() to return a more reasonable representation, and register a TypeAdapter which handles deserialization
  2. Only register a TypeAdapter which handles both serialization and deserialization, and use GsonBuilder.enableComplexMapKeySerialization()
  3. Only use GsonBuilder.enableComplexMapKeySerialization(). In that case Gson will use reflection to serialize and deserialize Tile instances

Also, as side note: Your Tile class looks a bit incorrect:

  • Normally when using a class as key of a Map you override equals and hashCode; 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 override equals(Object)
  • Just calling super.hashCode() in your hashCode() implementation has no special effect and behaves the same way as if you had not overridden the method
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement