Gson反序列化为Map泛型类型

时间:2011-09-21 16:36:04

标签: java json gson

尝试将JSON反序列化为Map< K,V>其中K是String,V是几种类型之一(即String int或boolean)。使用Gson,我尝试了以下代码:

public static void main(String[] args) {
JsonObject json = new JsonObject(); 
json.addProperty("str", "str-value");
json.addProperty("int", 10);
json.addProperty("bool", true);
// "json" now contains {"str":"str-value","int":10,"bool":true}
Type mapType = new TypeToken<Map<String, Object>>() {}.getType();
Gson gson = new Gson();
Map<String, Object> map = gson.fromJson(json, mapType);

String str = (String) map.get("str"); // cannot cast Object to String
str = String.valueOf(map.get("str")); // results in java.lang.Object@1632847
}

1 个答案:

答案 0 :(得分:2)

技术答案

如果您附加Gson源代码然后调试程序,您将找到问题的根源。这个问题似乎停留在Gson代码中。

由于值为Object类型,您调用fromJson(),因此将使用com.google.gson.ObjectNavigator类,并进入此段代码[~line 113]

else if (objTypePair.type == Object.class && isPrimitiveOrString(objectToVisit)) {
   visitor.visitPrimitive(objectToVisit); //Target value is the proper value after this call
   visitor.getTarget(); //target value is now a blank Object.

其中visitor是JSonObjectDeserializationVisitor类型,objectToVisit是你的值,objectTypePair是它的类型(Object)。

现在,JsonObjectDeserializationVisitor有一个名为construct的标志,默认设置为false。因此,当调用getTarget()方法时,它会检查构造的标志是否为true,否则它会创建您尝试创建的对象的新实例。由于构造的标志永远不会被设置,因此对getTarget()的调用将返回一个空白的Object。

在代码中调用getTarget()似乎是不必要的,并且似乎是问题的根源。 visitPrimitive通过将解析后的值放入将被传回的目标变量来执行适当的操作。这似乎是围绕对象类型的错误。

除非您愿意自定义构建Gson,否则这不是您可以解决的问题。我建议将其作为Gson论坛的报告提交。 版本1.5已经one report filed

解决方法

我认为有两种方法可以在短期内解决这个问题。

1)制作<String, String>类型的地图,虽然您丢失了类型,但仍然可以正确地获取值

2)首先将值放入bean类,然后将其序列化。

public class myObj{
  String myStr;
  int    myInt;
  boolean myBool;
  //get and set methods
}

public static void main(String args[]){
   MyObj o = new MyObj();
   o.setMyStr("str-value");
   Gson gson = new Gson();
   String json = gson.toJson(o);

   o = gson.fromJson(json, MyObj.class);
}

两者都打败了你想要做的事情的目的,但谷歌法院要解决这个我相信的错误。

相关问题