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

时间:2012-06-28 14:21:36

标签: java jackson

我有一张如下所示的地图:

public class VerbResult {
    @JsonProperty("similarVerbs")
    private Map<Verb, List<Verb>> 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]

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

3 个答案:

答案 0 :(得分:24)

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

首先在地图声明中:

@JsonDeserialize(keyUsing = MyCustomDeserializer.class)
private Map<Verb, List<Verb>> 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;
    }
}

与Jersey和Jackson 2.x合作

答案 1 :(得分:11)

如上所述,诀窍是你需要一个密钥反序列化器(这也让我感到困惑)。在我的例子中,在我的类上配置了非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() );

答案 2 :(得分:4)

建立answer given here,建议使用反序列化器实现模块。 JodaTime Module是一个易于理解的包含序列化器和反序列化器的模块的完整示例。

请注意,模块功能是在Jackson 1.7版中引入的,因此您可能需要升级。

一步一步:

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

    你将全部设定