尝试将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
}
答案 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);
}
两者都打败了你想要做的事情的目的,但谷歌法院要解决这个我相信的错误。