【问题标题】:deserialize a generics hashmap when key is not primitive当键不是原始的时反序列化泛型哈希图
【发布时间】:2011-03-27 14:27:45
【问题描述】:

我想使用泛型对哈希图进行 gson 和 de-gson。
当我的密钥是字符串时我可以成功,但如果它是 对象。
我这里有两个代码部分。第一个不起作用,第二个 做。

// doesnt work works
 try {
       TradableBean tradable = new TradableBean("Tradable");
       PositionBean position = new PositionBean(tradable);
       Map<TradableBean, PositionBean> map1 = new HashMap<TradableBean, PositionBean>();
       map1.put(tradable, position);
       String json1 = gson.toJson(map1);
       Map<TradableBean, PositionBean> map2 = gson.fromJson(json1, new TypeToken<Map<TradableBean, PositionBean>>(){}.getType());
       System.out.println(map2);
   } catch (Exception e) {
       System.out.println("failed");
   }

现在是工作部分 -

 // works - with string
   try {
       String tradable = new String("Tradable");
       PositionBean position = new PositionBean(new TradableBean("Tradable"));
       Map<String, PositionBean> map1 = new HashMap<String,PositionBean>();
       map1.put(tradable, position);
       String json1 = gson.toJson(map1);
       Map<String, PositionBean> map2 = gson.fromJson(json1, new TypeToken<Map<String, PositionBean>>() {}.getType());
       System.out.println(map2);
   } catch (Exception e) {
       System.out.println("failed");
   }

在我的 TradableBean 中:

@Override public int hashCode() {
   return getId();} 
@Override public boolean equals(Object obj) {
   boolean equals = false;
   if (obj instanceof AccountBean){
       TradableBean tradable_p = (TradableBean)obj;
       if (getId()==tradable_p.getId()){
           equals = true;
       }
   }
   return equals;

}

例外:

com.google.gson.JsonParseException: Expecting object found:
"TradableBean{id=0, tradableName='Tradable', moneyMultiplier=1,
expirationDate=null}"
       at
com.google.gson.JsonObjectDeserializationVisitor.visitFieldUsingCustomHandler(JsonObjectDeserializationVisitor.java:
100)
       at
com.google.gson.ObjectNavigator.navigateClassFields(ObjectNavigator.java:
150)
       at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:123)
       at
com.google.gson.JsonDeserializationContextDefault.fromJsonPrimitive(JsonDeserializationContextDefault.java:
84)
       at
com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:
53)
       at com.google.gson.DefaultTypeAdapters
$MapTypeAdapter.deserialize(DefaultTypeAdapters.java:531)
       at com.google.gson.DefaultTypeAdapters
$MapTypeAdapter.deserialize(DefaultTypeAdapters.java:498)
       at
com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:
50)

【问题讨论】:

    标签: generics gson


    【解决方案1】:

    丹的答案是正确的。

    您遇到的 Gson 限制涉及它当前如何序列化映射键:通过调用 toString()。来自MapTypeAdapter

    map.add(String.valueOf(entry.getKey()), valueElement);
    

    MapTypeAdapter 文档中也描述了此行为。

    这个实现实际上只适用于简单的原始类型作为映射键。如果键不是简单的原语,则对象是 {@code toString}ed 并且该值用作其键。

    如果您坚持使用自定义类型作为映射键,那么我可以告诉您,您将不得不编写自定义序列化程序和/或自定义反序列化程序和/或生成字符串表示形式的 toString()易于反序列化。

    另外,请查看MapAsArrayTypeAdapter 了解一种方法。 (它可以通过调用GsonBuilder.enableComplexMapKeySerialization() 来使用,而不是通过文档描述的直接实例化(因为它目前不是公共类)。我没有测试它以查看它的实现是否有效,但它看起来很有希望。)

    【讨论】:

      【解决方案2】:

      我认为您需要编写自己的custom serializator

      更新:说明是个例外:

      com.google.gson.JsonParseException: Expecting object found: "TradableBean{id=0, tradableName='Tradable', moneyMultiplier=1, expirationDate=null}"
      

      前置字符串“TradableBean”似乎是由使用某种toString() 的序列化编写的。反序列化需要{id=0,... }形式的对象

      【讨论】:

      • 您好,我使用 TradableBean 的默认序列化,只要我通过它,它就可以正常工作。它没有在 api 中说它不应该在 map 的键上使用常规反序列化。我错了吗?
      • 您好,感谢您提供新数据。我删除了前置字符串,但仍然没有结果。我也尝试删除我的 toString。它究竟在等待进入 key 对象的 toString 是什么? ?我还应该编写自定义序列化吗?
      • @450602:是的,自定义序列化是两面的硬币。大多数情况下,您需要实现两个方向。此外,Gson.decode() 上有严格的标志...看看是否有任何效果。
      • 我几乎找不到这方面的文档。您发送给我的链接不提供 eaxaple。如果你知道的话,放在这里就好了
      • @450602:很抱歉你没有发现它有用。然而,它是最权威的文献。您可能想在这里查看 gson 测试套件:code.google.com/p/google-gson/source/browse/…
      猜你喜欢
      • 1970-01-01
      • 2014-02-21
      • 2015-08-03
      • 1970-01-01
      • 2012-05-28
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 1970-01-01
      相关资源
      最近更新 更多