Jackson用Javax约束验证将地图数组反序列化为TreeMap

时间:2018-07-20 17:11:11

标签: java spring spring-boot jackson

我编写了自定义JsonDeserializer,用于反序列化地图数组:

"fieldNr2": [
    {
        "3.0": 3.1
    },
    {
        "2.0": 2.1
    },
    {
        "4.0": 4.1
    },
    {
        "5.0": 5.1
    },
    {
        "1.0": 1.1
    }
]

使用Javax验证到TreeMap:

TreeMap<@Positive BigDecimal, @NotNull @Positive BigDecimal>

问题是我不知道如何在ObjectCodec.readValue()方法中定义映射数组(具有键和值的指定类)。我尝试使用TypeReference失败。

我的代码在哪里

class TreeMapDeserializer extends JsonDeserializer<TreeMap<BigDecimal, BigDecimal>> {

@Override
public TreeMap<BigDecimal, BigDecimal> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {

    ObjectCodec oc = jsonParser.getCodec();
    TreeMap<BigDecimal, BigDecimal>[] input = oc.readValue(jsonParser, TreeMap[].class);

    TreeMap<BigDecimal, BigDecimal> output = new TreeMap<>();
    for (TreeMap map : input) {
        Map.Entry<BigDecimal, BigDecimal> mapEntry = (Map.Entry<BigDecimal, BigDecimal>) map.entrySet().stream().findFirst().get();

        BigDecimal key = mapEntry.getKey();
        BigDecimal value = mapEntry.getValue();
        output.put(key, value);
    }

    return output;
}

此外,当我注释掉javax约束验证时。应用程序运行没有问题,但是当我重新打开它时,杰克逊无法将String解析为BigDecimal(?)或无法将Double解析为BigDecimal(?)。

Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: java.lang.String cannot be cast to java.math.BigDecimal; nested exception is com.fasterxml.jackson.databind.JsonMappingException: java.lang.String cannot be cast to java.math.BigDecimal (through reference chain:

2 个答案:

答案 0 :(得分:0)

您可以执行以下操作。您的键值是String和Double。

integer

答案 1 :(得分:0)

解决方案:

public TreeMap<BigDecimal, BigDecimal> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {

    ObjectCodec oc = jsonParser.getCodec();
    List<Map.Entry<BigDecimal, BigDecimal>> input = oc.readValue(jsonParser, new TypeReference<List<Map.Entry<BigDecimal, BigDecimal>>>(){});

    Map<BigDecimal, BigDecimal> intermediateMap = input.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    return new TreeMap<>(intermediateMap);
}

public Map<SecretClass, BigDecimal> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {

    ObjectCodec oc = jsonParser.getCodec();
    List<Map.Entry<SecretClass, BigDecimal>> input = oc.readValue(jsonParser, new TypeReference<List<Map.Entry<SecretClass, BigDecimal>>>(){});

    return input.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}