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

Max*_*Max 18 java jackson

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

public class VerbResult {
    @JsonProperty("similarVerbs")
    private Map<Verb, List<Verb>> similarVerbs;
}
Run Code Online (Sandbox Code Playgroud)

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

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);
    }
    //...
}
Run Code Online (Sandbox Code Playgroud)

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

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

Jap*_*eva 27

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

首先在地图声明中:

@JsonDeserialize(keyUsing = MyCustomDeserializer.class)
private Map<Verb, List<Verb>> similarVerbs;
Run Code Online (Sandbox Code Playgroud)

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

适用于Jersey和Jackson 2.x


小智 12

如上所述,诀窍是你需要一个密钥解串器(这也引起了我的注意).在我的例子中,我的类上配置了一个非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() );
Run Code Online (Sandbox Code Playgroud)


fvu*_*fvu 5

此处给出答案的基础上,建议使用反序列化器实现模块。所述JodaTime模块是一个易于理解的含有串行解串器模块的完整的例子。

请注意,杰克逊版本1.7中引入了模块功能,因此您可能需要升级。

所以一步一步来:

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

一切都会好起来的

  • @Max也许可以提供有关如何实现解串器的代码?我希望看到,如果可能=) (5认同)
  • 另外需要注意的一点是:您需要添加的是“密钥(反)序列化器”:常规(反)序列化器不能原样使用,因为Map密钥还有其他限制。但是可以肯定从模块完成注册。 (4认同)