如何让杰克逊找到我的密钥解串器?

时间:2019-12-20 03:26:49

标签: java jackson

这是我的课程(省略了getter和setter的内容):

public class ClassWithAMap {

    @JsonProperty("map")
    @JsonDeserialize(keyUsing = RangeDeserializer.class)
    private Map<Range<Instant>, String> map;

    @JsonCreator
    public ClassWithAMap(Map<Range<Instant>, String> map) {
      this.map = map;
    }

  }

RangeSerializer看起来像这样:

public class RangeDeserializer extends KeyDeserializer {

    public ObjectMapper objectMapper() {
        return new ObjectMapper()
            .registerModules(
                new JavaTimeModule(),
                new Jdk8Module(),
                new GuavaModule(),
                new ParameterNamesModule());
    }

    @Override
    public Range<Instant> deserializeKey(String key, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        TypeReference<Range<Instant>> typeRef = new TypeReference<Range<Instant>>() {
        };
        Range<Instant> range = objectMapper().readValue(key, typeRef);
        return range;
    }
}

使用这些代码的主要代码如下:

        Map<Range<Instant>,String> map = new HashMap<>();
        Range<Instant> key = Range.greaterThan(Instant.now());
        map.put(key, "some value");
        ClassWithAMap classWithAMap = new ClassWithAMap(map);

        String jsonInput = objectMapper()
                .writerWithDefaultPrettyPrinter()
                .writeValueAsString(classWithAMap);

        ClassWithAMap classWithMap = objectMapper()
                .readValue(jsonInput,
                ClassWithAMap.class);

最后一条语句给我这个错误:

InvalidDefinitionException: Cannot find a (Map) Key deserializer for type [simple type, class com.google.common.collect.Range<java.time.Instant>]

而且,可以肯定的是,它从不调用我的解串器。我已经错过了注册反序列化器的步骤,尽管我将其与使用自定义类而不是Range<Instant>的类似设置进行了比较,但效果很好,我看不出有什么区别。有人知道我做错了吗?我猜想与泛型有关,但是我还没有进一步。

我正在使用杰克逊2.9.9和Java 1.8。

1 个答案:

答案 0 :(得分:1)

您需要将所有注释移至构造函数:

class ClassWithAMap {

    private Map<Range<Instant>, String> map;

    @JsonCreator
    public ClassWithAMap(
            @JsonProperty("map")
            @JsonDeserialize(keyUsing = RangeDeserializer.class)
            Map<Range<Instant>, String> map) {
        this.map = map;
    }
}