使用Jackson反序列化非字符串映射键

我有一个看起来像这样的地图:

public class VerbResult { @JsonProperty("similarVerbs") private Map<Verb, List> similarVerbs; } 

我的动词类看起来像这样:

 public class Verb extends Word { @JsonCreator public Verb(@JsonProperty("start") int start, @JsonProperty("length") int length, @JsonProperty("type") String type, @JsonProperty("value") VerbInfo value) { super(length, length, type, value); } //... } 

我想序列化和反序列化我的VerbResult类的实例,但是当我这样做时,我得到这个错误: Can not find a (Map) Key deserializer for type [simple type, class my.package.Verb]

我在网上看到你需要告诉jackson如何反序列化地图密钥,但我没有找到任何解释如何进行此操作的信息。 动词类也需要在地图之外进行序列化和反序列化,因此任何解决方案都应保留此function。

基于此处给出的答案 ,建议使用反序列化器实现模块。 JodaTime模块是一个易于理解的包含序列化器和反序列化器的模块的完整示例。

请注意,Jackson版本1.7中引入了Modulefunction,因此您可能需要升级。

所以一步一步:

  1. 根据Joda示例为您的类创建一个包含(de)序列化程序的模块
  2. 使用mapper.registerModule(module);注册该模块mapper.registerModule(module);

你会全力以赴

经过一天的搜索,我发现了一个基于这个问题的简单方法。 解决方案是将@JsonDeserialize(keyUsing = YourCustomDeserializer.class)注释添加到地图中。 然后通过扩展KeyDeserializer并覆盖KeyDeserializer方法来实现自定义反deserializeKey 。 将使用字符串键调用该方法,您可以使用该字符串构建实际对象,甚至可以从数据库中获取现有对象。

首先在地图声明中:

 @JsonDeserialize(keyUsing = MyCustomDeserializer.class) private Map> similarVerbs; 

然后创建将使用字符串键调用的反序列化器。

 public class MyCustomDeserializer extends KeyDeserializer { @Override public MyMapKey deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException { //Use the string key here to return a real map key object return mapKey; } } 

适用于泽西岛和jackson2.x.

如上所述,诀窍是你需要一个密钥解串器(这也引起了我的注意)。 在我的例子中,我的类上配置了一个非String映射键,但它不在我正在解析的JSON中,所以一个非常简单的解决方案对我有效(只需在密钥解串器中返回null)。

 public class ExampleClassKeyDeserializer extends KeyDeserializer { @Override public Object deserializeKey( final String key, final DeserializationContext ctxt ) throws IOException, JsonProcessingException { return null; } } public class ExampleJacksonModule extends SimpleModule { public ExampleJacksonModule() { addKeyDeserializer( ExampleClass.class, new ExampleClassKeyDeserializer() ); } } final ObjectMapper mapper = new ObjectMapper(); mapper.registerModule( new ExampleJacksonModule() );