serialization - 使用 jackson 序列化 Map.Entry 时出现问题

标签 serialization junit jackson deserialization junit4

如果我尝试反序列化以下存储为字符串的类型:

 List<Entry<String, String>> entryList;

其中 entryList 包含:
[{"dummyKey1":"dummyValue1"}]

我收到以下错误
 Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.util.Map$Entry, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information.

在junit中运行测试用例时出现上述错误,但如果我删除测试用例,则在部署后一切正常:

由于 Entry 中缺少 NoArgsConstructor,在运行 junit 测试用例时出现上述错误。因此,我创建了一个带有 NoArgsConstructor 的 DummyEntry,它调用带有 null 参数的 Entry。
   DummyEntry<K, V> extends SimpleEntry<K, V>

进行此更改后,没有出现上述错误,但在部署更改后我开始出现以下错误。
  Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:
  Unrecognized field "dummyKey1", not marked as ignorable (2 known properties: "value", "key"]).

一种方式不适用于junit,但在生产中它可以工作,而另一种方式在junit中工作但在生产中不起作用的原因是什么。

另外,我还注意到一件事:在生产中,Map.Entry 被序列化为
  {'dummyKey1':'dummyValue1'}

而 junit 中的测试用例序列化相同的字符串
 {'key':'dummyKey1', 'value':'dummyValue1'}

这种奇怪行为的原因是什么?我怎样才能让这件事对两者都有效?

最佳答案

我怀疑您可能遇到了 Map.Entry 的不同序列化策略的问题。 .

在 v2.5.0 (IIRC) of jackson-databind Map.Entry was supported as a 'known type' .在此版本之前,keyvalue Map.Entry 的属性将出现在序列化的 Map.Entry 中。在此版本之后,情况不再如此。

以下是一些示例测试用例,显示了我的意思:

@Test
public void mapSerialisationPreJackson2_5_0() throws IOException {
  Map<String, String> aMap = Maps.newHashMap();
  aMap.put("dummyKey1", "dummyValue1");

  Set<Map.Entry<String, String>> incoming = aMap.entrySet();

  ObjectMapper objectMapper = new ObjectMapper();

  String serialised = objectMapper.writeValueAsString(incoming);

  // prints: [{"key":"dummyKey1","value":"dummyValue1"}]
  System.out.println(serialised);

  Set<Map.Entry<String, String>> deserialised = objectMapper.readValue(serialised, Set.class);

  // prints: [{key=dummyKey1, value=dummyValue1} (just like you posted in your question) whereas for versions > 2.5.0 the serialised form is ]
  System.out.println(deserialised);
}

@Test
public void mapSerialisationPostJackson2_5_0() throws IOException {
  Map<String, String> aMap = Maps.newHashMap();
  aMap.put("dummyKey1", "dummyValue1");

  Set<Map.Entry<String, String>> incoming = aMap.entrySet();

  ObjectMapper objectMapper = new ObjectMapper();

  String serialised = objectMapper.writeValueAsString(incoming);

  // prints: [{"dummyKey1":"dummyValue1"}]
  System.out.println(serialised);

  Set<Map.Entry<String, String>> deserialised = objectMapper.readValue(serialised, Set.class);

  // prints: [{dummyKey1=dummyValue1}]
  System.out.println(deserialised);
}

在 v2.5.0 之前,Map.Entry 将被序列化为 {key=dummyKey1, value=dummyValue1} (就像您在问题中发布的一样)而对于版本 > 2.5.0 的序列化形式是 {dummyKey1=dummyValue1} .

我认为您在测试环境中使用的是 < 2.5.0 的 jackson-databind 版本,而在生产环境中使用的是 > 2.5.0 的 jackson-databind 版本

关于serialization - 使用 jackson 序列化 Map.Entry 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45534922/

相关文章:

javascript - 序列化 JS 对象以供离线使用

maven - 跳过 Maven 中的一些测试

java - 将数据结构从 java 传递到 perl(反之亦然)

java - 是否建议仅增加 junit 的方法范围?

java - @RunWith(MockitoJUnitRunner.class) 和 @RunWith(SpringJUnit4ClassRunner.class) 有什么区别?什么时候合适使用它?

java - 将多个任意注释合并为一个

java - FasterXML Jackson Smile 与 json

java - 使用 @JsonSubTypes 进行反序列化以获得无值 - 缺少属性错误

c# - 提高代码序列化速度的更好方法

python - Django 序列化器中的外部图像数组