为什么Google JSON库无法正确序列化此HashMap?

时间:2013-05-28 04:53:03

标签: java json gson

我有两个HashMaps使用Google Gson库序列化为JSON:

    final Map<String, String> map1 = new HashMap<String, String>() {
        {
            put("abc", "def");
        }
    };

    final Map<String, String> map2 = new HashMap<String, String>();
    map2.put("abc", "def");

    final Gson gson = new Gson();
    final String s1 = gson.toJson(map1); // "null"
    final String s2 = gson.toJson(map2); // {"abc":"def"}

为什么第二个HashMap正确序列化但不是第一个HashMap?

1 个答案:

答案 0 :(得分:6)

Gson使用反射,并不关心类是否实现Serializable。但是,Gson确实需要一个无参数构造函数(参见design doc):

  

Gson需要在反序列化之前创建一个虚拟类实例   Json数据进入其字段......我们通过调用它来创建类实例   无参数构造函数......

当您致电toJson(Object obj)时,Gson将使用obj.getClass()来确定如何构建obj的“虚拟实例”,在您的情况下,这是一个匿名内部上课。内部类需要引用它们的包含类才能构造。序列化时无法引用外部类,这就是您的结果为null的原因。您可以通过向Gson提供有关如何构造对象的更多信息来解决此问题:

final Map<String, String> map1 = new HashMap<String, String>() {
  {
    put("abc", "def");
  }
};
Gson gson = new Gson();
String json = gson.toJson(map1, new TypeToken<Map<String, String>>() {}.getType()); // {"abc":"def"}

修改:请注意,这仅适用,因为您的匿名类可以转换为Map<String, String>。如果你有一个更复杂的内部类,例如:

final Map<String, String> map1 = new HashMap<String, String>() {
  private String additionalData = "Foo";

  {
    put("abc", "def");
  }
};

additionalData不在输出中。