【问题标题】:Jackson deserializing array of maps, to TreeMap with javax constraint validationJackson 将地图数组反序列化为带有 javax 约束验证的 TreeMap
【发布时间】:2018-07-20 17:11:10
【问题描述】:

我为反序列化地图数组编写了自定义 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 约束验证时。应用程序运行没有问题,但是当我重新打开它时,Jackson 无法尝试将 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:

【问题讨论】:

    标签: java spring spring-boot jackson


    【解决方案1】:

    你可以做这样的事情。您的键值是 String 和 Double 类型。

    public static Map<String, String> gsonMap2Map(JsonParser parser) throws IOException {
        ObjectCodec codec = parser.getCodec();
        TreeNode node = codec.readTree(parser);
        TreeMap<String, Double> ret = new TreeMap<String, Double>();
        if (node.isObject()) {
            for (Iterator<String> iter = node.fieldNames(); iter.hasNext();) {
                String fieldName = iter.next();
                TreeNode field = node.get(fieldName);
                if (field != null) {
                    ret.put(fieldName, field.toDouble());
                } else {
                    ret.put(fieldName, "null");
                }
            }
        }
        return ret;
    }
    

    【讨论】:

    • 感谢您的快速回复。就我而言,您的代码用于反序列化地图,而不是地图数组。尽管如此,这是非常好的方法。我用这个(新评论)解决了我的问题。
    【解决方案2】:

    解决方案:

    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));
    }
    

    【讨论】:

      猜你喜欢
      • 2012-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 2018-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多