【问题标题】:Gson de-serialize to Map generic typeGson 反序列化为 Map 泛型类型
【发布时间】:2011-09-21 16:36:03
【问题描述】:

尝试将 JSON 反序列化为 Map,其中 K 是字符串,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
}

【问题讨论】:

    标签: java json gson


    【解决方案1】:

    技术解答

    如果你附上Gson源代码然后调试程序你会找到问题的根源。问题似乎在于 Gson 代码。

    由于值是您调用 fromJson() 的 Object 类型,因此将使用类 com.google.gson.ObjectNavigator 并进入这部分代码 [~第 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 有一个名为 constructor 的标志,默认设置为 false。因此,当调用 getTarget() 方法时,它会检查构造的标志是否为真,如果不是,它会创建您尝试创建的对象的新实例。因为构造的标志从未设置,所以对 getTarget() 的调用返回一个空白对象。

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

    除非您愿意对 Gson 进行自定义构建,否则您无法解决此问题。我建议将此作为报告提交给 Gson 论坛。 1.5版已经有one report filed了

    解决方法

    我看到了两种可以在短期内解决此问题的方法。

    1) 制作&lt;String, String&gt; 类型的 Map,虽然丢失了类型,但仍然可以正确取回值

    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);
    }
    

    两者都违背了你试图做的事情的目的,但我相信在谷歌法庭上修复这个错误。

    【讨论】:

    • 查看问题,感谢您的澄清。到目前为止,Gson 似乎希望提供静态类型而不是 Object 类型。无论如何,这是一个阻塞问题。
    猜你喜欢
    • 1970-01-01
    • 2013-08-26
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多