当键不是原始值时反序列化泛型哈希图

发布于 2024-10-27 04:50:51 字数 2721 浏览 0 评论 0 原文

我想使用泛型对哈希图进行 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:期望找到对象:
"TradableBean{id=0, tradableName='可交易', MoneyMultiplier=1,
过期日期=空}”
       在
com.google.gson.JsonObjectDeserializationVisitor.visitFieldUsingCustomHandler(JsonObjectDeserializationVisitor.java:
100)
       在
com.google.gson.ObjectNavigator.navigateClassFields(ObjectNavigator.java:
150)
       在 com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:123)
       在
com.google.gson.JsonDeserializationContextDefault.fromJsonPrimitive(JsonDeserializationContextDefault.java:
84)
       在
com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:
53)
       在 com.google.gson.DefaultTypeAdapters
$MapTypeAdapter.deserialize(DefaultTypeAdapters.java:531)
       在 com.google.gson.DefaultTypeAdapters
$MapTypeAdapter.deserialize(DefaultTypeAdapters.java:498)
       在
com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:
50)

I want to gson and de-gson a hashmap with generics.
I can do it successfully when my key is a string but not if it is an
object.
I have the two code part here . the first doesnt work and the second
does.

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

and now the working part -

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

and in the TradableBean I have:

@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;

}

the exception:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

万水千山粽是情ミ 2024-11-03 04:50:51

丹的回答是正确的。

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

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

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

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

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

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

Dan's answer is on the right track.

The Gson limitation you're bumping up against concerns how it currently serializes map keys: by calling toString(). From MapTypeAdapter:

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

This behavior is also described in the MapTypeAdapter documentation.

This implementation really only works well with simple primitive types as the map key. If the key is not a simple primitive then the object is {@code toString}ed and that value is used as its key.

If you insist on using custom types as map keys, then as best I can tell you're going to have to write a custom serializer and/or a custom deserializer and/or a toString() that generates a string representation that's easy to deserialize.

Also, take a look at MapAsArrayTypeAdapter for one approach. (It's usable with a call to GsonBuilder.enableComplexMapKeySerialization(), not through direct instantiation as the docs describe (because it's currently not a public class). I didn't test it to see if its implementation works, but it looks promising.)

紧拥背影 2024-11-03 04:50:51

我认为您需要编写自己的 自定义序列化器

更新: 例外是:

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

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

I think you need to write your own custom serializator.

Update: the tell-tale is the exception:

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

The prepending string "TradableBean" seems to be written by a serialization that uses some sort of toString(). the Deserialization expected an object of the form {id=0,... }

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文