HashMap<MyObject, List<Integer> 与 Jackson 的序列化和反序列化

Posted

技术标签:

【中文标题】HashMap<MyObject, List<Integer> 与 Jackson 的序列化和反序列化【英文标题】:Serialization and deserialization of HashMap<MyObject, List<Integer> with Jackson 【发布时间】:2019-06-11 16:19:52 【问题描述】:

我目前正在开发一个小型 android 应用程序,该应用程序需要能够使用 Jackson 库通过序列化/反序列化来保存/恢复一系列设置。 对于大多数部分,它工作得非常好,我可以序列化我的对象并再次恢复它们。 现在我需要使用以下类型序列化/反序列化私有成员:

HashMap<Model, List<Integer>>

模型是我自己的对象之一,包含一堆简单的值 + getter/setter 方法。 这就是我遇到问题的地方。它开始向我抛出以下错误:

DataAccess: Cannot find a (Map) Key deserializer for type [simple type, class com.schulz.toolie.Models.Model] at [Source: (String)""; line: 1, column: 1]

我尝试在 getter/setter 方法上设置 @JsonAnyGetter 和 @JsonAnySetter 之类的注释,以及在 getter、setter 和变量上设置 @JsonProperty("subscribe")。

有没有办法解决这个问题?最好不要编写自定义的序列化/反序列化方法,因为我会得到很多这样的方法。

【问题讨论】:

我很困惑。 对于这样的字段,生成的 JSON 会是什么 可能类似于 [ ["var1": "", "var2": 123, "var3": "xxx"], [1,4,5,7,5,4,3, 3]] 首先,我不明白从地图开始时这些东西是从哪里来的。二,这不是有效的 JSON。 是的,它是为了让您了解我猜它会是什么样子。对我来说,数据的外观并不那么重要,因为除了序列化和反序列化之外,它不用于任何用途 嗯,Jackson 的目标不是“把任何东西塞进去,然后它会找到一种方法把它变成 JSON 格式”。就是把它转成JSON形式才有意义。 【参考方案1】:

您的问题是 Jackson 有一个将 Map 转换为 JSON 的标准。地图的键用作结果 JSON 中的属性名称。

Map<String, Double> groceryPrices = new HashMap<>();
groceryPrices.put("apple", 0.25);
groceryPrices.put("orange", 0.30);

这自然会转换为 JSON 对象:


  "apple": 0.25,
  "orange": 0.30

问题是您正在使用一个复杂的对象来表示一个键。没有简单的方法可以将复杂对象序列化和反序列化到字符串或从字符串中反序列化。

如果你不想写自定义序列化,我建议你改变你的数据结构。您当前的结构将模型与其整数联系在一起。您可以将整数列表折叠到模型对象本身中:

Map<String, Model> models; // This could map modelId -> Model which now contains the integers

【讨论】:

谢谢。说得通。我决定选择将模型放在单独的列表中,然后在每个模型中使用 modelId 作为我的 HashMap 中的键。需要进行一些重构,我认为从长远来看会更好

以上是关于HashMap<MyObject, List<Integer> 与 Jackson 的序列化和反序列化的主要内容,如果未能解决你的问题,请参考以下文章

类型安全:从 Object 到 List<MyObject> 的未经检查的强制转换

为啥 WCF 会返回 myObject[] 而不是 List<T> 像我期望的那样?

如何使用 Dapper 将 list<myobject> 作为参数插入到存储过程

HashMap 和 int 作为键

如何使用 DBUtils 查询 Set<MyObject>?

验证Mockito中的List列表参数