简体   繁体   中英

Gson ignores custom Serializer for Key in a Map

I am trying do serialize/deserialize a Map to JSON using GSON

I have a map that is defined by

HashMap<Test, List<Something>> map = 
  new HashMap<>();

Which includes two simple classes that are defined like this

class Test {
 public Test(){}
 public Test(String str){test = str;}
 String test;
}

class Something {
 public Something(){}
 public Something(String str){something = str;}
 String something;
}

and some test code like this

List<Something> somelist = new ArrayList<Something>();

somelist.add(new Something("something1"));
somelist.add(new Something("something2"));

map.put(new Test("test1"), somelist);

Gson does not seem able to serialize this by default and produces the following result

{
  "test.TestJsonClass$Test@15db9742": [
    {
      "string": "something1"
    },
    {
     "string": "something2"
    }
  ]
}

Which is somewhat expected, however, I then try to create a custom serializer for the class like this

Gson gson = new GsonBuilder().setPrettyPrinting()
    .registerTypeAdapter(Test.class, new JsonSerializer<Test>() {
      public JsonElement serialize(Test arg0, Type arg1,
          JsonSerializationContext arg2) {
        return new JsonPrimitive(arg0.test);
      }
    }).registerTypeAdapter(Something.class, new JsonSerializer<Something>() {

      @Override
      public JsonElement serialize(Something arg0, Type arg1,
          JsonSerializationContext arg2) {
        return new JsonPrimitive(arg0.something);
      }
    }).create();

This correctly serializes the Value (Something) but Gson seems to ignore my serializer for The Key (Test) and produces the following result

{
  "test.TestJsonClass$Test@15db9742": [
    "something1",
    "something2"
 ]
}

How can I make Gson correctly serialize my keys?

The easiest way I've found seems to be to to set the enableComplexMapKeySerialization() option when initially building your Gson object.

This forces Gson to serialize the keys using the standard rules, rather than just calling toString() on it. You can then add your own serializer/deserializer as required or just let Gson handle it.

More info here

Gson's Map support works by using String.valueOf(key) (which is just (obj == null) ? "null" : obj.toString() ) to serialize your keys and the standard TypeAdapters to deserialize them. Values are always handled by the TypeAdapters.

With that in mind, in order for your Map to serialize and deserialize according to what you've described, you need to override the toString method on Test and provide a JsonDeserializer for deserializing it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM