当key不是原始时,反序列化泛型hashmap

时间:2011-03-27 14:27:45

标签: generics gson

我希望gson和de-gson使用泛型的hashmap 当我的密钥是字符串时,我可以成功地完成它,但如果它是一个字符串则不能 对象。
我在这里有两个代码部分。第一个不起作用,第二个起作用 确实。

// 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)

2 个答案:

答案 0 :(得分:2)

丹的回答是正确的。

Gson限制你正在考虑它当前如何序列化地图键:通过调用toString()。来自MapTypeAdapter

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

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

  

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

如果您坚持使用自定义类型作为地图密钥,那么我可以告诉您将要编写自定义序列化程序和/或自定义反序列化程序和/或生成字符串的toString()表示很容易反序列化。

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

答案 1 :(得分:1)

我认为你需要自己编写custom serializator

更新:告诉是例外:

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

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

形式的对象