TreeMap 的自定义反序列化器 - 无法通过 JsonParser 获取全文

问题描述

我有一个类定义如下:

class Rule {
    private final TreeMap<String,String> rule;
    public Rule(TreeMap<String,String> rule) {
        this.rule = rule;
    }
}

一个类包含此类对象的列表:

class BigClass {
    
    @JsonProperty("rules")
    @JsonDeserialize(contentUsing = Rule.Deserializer.class)
    private final List<Rule> rules;

    //...

}

... 并且如 @JsonDeserialize 注释中所指定,我希望此类列表的内容自定义反序列化器处理。

为此,我将 JsonDeserializer<Rule> 扩展如下:

public static final class Deserializer extends JsonDeserializer<Rule> {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public Rule deserialize(JsonParser p,DeserializationContext ctxt) throws IOException {
        String strRule = p.getText();
        TypeReference<TreeMap<String,String>> typeReference = new TypeReference<>() {
        };

        TreeMap<String,String> ruleMap = objectMapper.readValue(strRule,typeReference);
        return new Rule(ruleMap);
    }
}

当我尝试使用以下结构解析 BigClass 类型的 Json 时:

{
    ...
    "rules": [
        {
            "A": "B","C": "D","E": "F" 
        }
    ]
}

...我在自己的 deserialize() 方法中被正确调用,但问题是表达式 p.getText() 只返回我 {(第一个标记),因此反序列化失败。

我试图将所有内容都放在同一行(没有回车),但我遇到了同样的问题。 这看起来很明显很简单,但我在网上和杰克逊文档中都找不到任何例子。 有什么建议或参考可以分享吗?

解决方法

改变你的反序列化方法如下: 您在反序列化步骤中阅读了整个 JsonNode,并根据您在节点中找到的键值构建您自己的 TreeMap。 (您可能需要向 Rule 类添加构造函数)

@Override
  public Rule deserialize(JsonParser p,DeserializationContext ctxt) throws IOException {
    JsonNode node = p.getCodec().readTree(p);
    TreeMap<String,String> ruleMap = new TreeMap<>();
    node.fields().forEachRemaining(e -> ruleMap.put(e.getKey(),e.getValue().textValue()));

    return new Rule(ruleMap);
  }