Gson 忽略映射中键的自定义序列化程序

Dou*_*ive 4 java serialization json map gson

我正在尝试使用 GSON 将 Map 序列化/反序列化为 JSON

我有一个由以下定义的地图

HashMap<Test, List<Something>> map = 
  new HashMap<>();
Run Code Online (Sandbox Code Playgroud)

其中包括两个像这样定义的简单类

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

class Something {
 public Something(){}
 public Something(String str){something = str;}
 String something;
}
Run Code Online (Sandbox Code Playgroud)

和一些像这样的测试代码

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

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

map.put(new Test("test1"), somelist);
Run Code Online (Sandbox Code Playgroud)

默认情况下,Gson 似乎无法序列化它并产生以下结果

{
  "test.TestJsonClass$Test@15db9742": [
    {
      "string": "something1"
    },
    {
     "string": "something2"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

然而,这有点在意料之中,然后我尝试为这样的类创建一个自定义序列化程序

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();
Run Code Online (Sandbox Code Playgroud)

这正确序列化了 Value (Something) 但 Gson 似乎忽略了我的 Key (Test) 序列化程序并产生以下结果

{
  "test.TestJsonClass$Test@15db9742": [
    "something1",
    "something2"
 ]
}
Run Code Online (Sandbox Code Playgroud)

如何让 Gson 正确序列化我的密钥?

Dav*_*rch 5

我发现的最简单的方法似乎是在最初构建 Gson 对象时设置 enableComplexMapKeySerialization() 选项。

这会强制 Gson 使用标准规则序列化键,而不是仅对其调用 toString()。然后,您可以根据需要添加自己的序列化器/解串器,或者让 Gson 处理它。

更多信息在这里


小智 1

Gson 的 Map 支持通过使用String.valueOf(key)(即(obj == null) ? "null" : obj.toString())来序列化您的键并使用标准 TypeAdapter 来反序列化它们。值始终由 TypeAdapter 处理。

考虑到这一点,为了让您的 Map 根据您所描述的内容进行序列化和反序列化,您需要重写 Test 上的 toString 方法并提供一个 JsonDeserializer 来对其进行反序列化。