【问题标题】:JSON/ Jackson: Recursive polymorphic deserialization without type fieldJSON/杰克逊:没有类型字段的递归多态反序列化
【发布时间】:2021-08-19 23:44:28
【问题描述】:

我目前正在努力处理类似于这样的 JSON 数据结构的反序列化:

示例 1:

{
    "condition": "AND",
    "rules": [
        {
            "id": "FIELD1",
            "field": "FIELD1",
            "type": "string",
            "input": "select",
            "operator": "equal",
            "value": [
                "a1"
            ]
        },
        {
            "id": "FIELD2",
            "field": "FIELD2",
            "type": "string",
            "input": "select",
            "operator": "in",
            "value": [
                "b1"
            ]
        }
    ]
}

示例 2:

{
    "condition": "AND",
    "rules": [
        {
            "id": "FIELD1",
            "field": "FIELD1",
            "type": "string",
            "input": "select",
            "operator": "equal",
            "value": [
                "a1"
            ]
        },
        {
            "id": "FIELD2",
            "field": "FIELD2",
            "type": "string",
            "input": "select",
            "operator": "in",
            "value": [
                "b1",
                "b2",
                "b3"
            ]
        },
        {
            "id": "FIELD3",
            "field": "FIELD3",
            "type": "string",
            "input": "select",
            "operator": "in",
            "value": [
                "c1",
                "c2",
                "c3"
            ]
        },
        {
            "id": "FIELD4",
            "field": "FIELD4",
            "type": "string",
            "input": "select",
            "operator": "in",
            "value": [
                "d1",
                "d2",
                "d3"
            ]
        },
        {
            "condition": "AND",
            "rules": [
                {
                    "id": "FIELD5",
                    "field": "FIELD5",
                    "type": "string",
                    "input": "select",
                    "operator": "equal",
                    "value": [
                        "e1"
                    ]
                },
                {
                    "id": "FIELD6",
                    "field": "FIELD6",
                    "type": "string",
                    "input": "select",
                    "operator": "in",
                    "value": [
                        "f1",
                        "f1",
                        "f3",
                        "f4",
                        "f5",
                        "f6"
                    ]
                },
                {
                    "condition": "AND",
                    "rules": [
                        {
                            "id": "FIELD7",
                            "field": "FIELD7",
                            "type": "string",
                            "input": "select",
                            "operator": "in",
                            "value": [
                                "g1",
                                "g2",
                                "g3"
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

我必须处理这种结构的许多实例。它是规则构建器的输出。我无法更改 JSON 的格式,我必须使用我得到的东西。结构是递归的,可以有多个层次。

我正在使用 Jackson 的 ObjectMapper 并构建一些内部类来映射数据。

static class Wrapper {
        public Condition condition;

        @JsonIgnoreProperties(ignoreUnknown = true)
        @JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
        @JsonSubTypes({
            @JsonSubTypes.Type(RuleGroup.class),
            @JsonSubTypes.Type(Rule.class) })
        public List<AbstractRuleObject> rules;
    }

    static abstract class AbstractRuleObject {
        public Condition condition;
        public List<Rule> rules;

        @JsonIgnoreProperties(ignoreUnknown = true)
        @JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
        @JsonSubTypes({
            @JsonSubTypes.Type(RuleGroup.class),
            @JsonSubTypes.Type(Rule.class) })
        public List<AbstractRuleObject> ruleGroups;
    }

    static class RuleGroup extends AbstractRuleObject {
        public Condition condition;
        public List<Rule> rules;
    }

    static class Rule extends AbstractRuleObject {
        public String id;
        public String field;
        public String type;
        public String input;
        public Operator operator;
        public List<String> value;
    }

大多数实例看起来像示例 1,对于那些已经可以正常工作的实例,但还有更复杂的示例,例如示例 2,实际上比示例 2 更复杂、更深入,但结构始终相同:

总是有一个“RuleGroup”,其中包含一个“Condition”和一个“Rule”列表,规则可以是“Rule”,也可以是“RuleGroup”,你可以走多远没有限制,但是我相信它不会超过 4 或 5 个级别。每个级别可以有多个“规则组”

我无法解析这些更深层次的示例,使用当前代码和示例 2 我收到以下错误:

无法解析 [简单类型,类 MyClass$AbstractRuleObject]:无法推断出唯一的子类型 MyClass$AbstractRuleObject(2个候选人匹配)

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    Rule 和 RuleGroup 没有任何共同之处,只是它们都可以出现在一个列表中,所以 AbstractRuleObject 不应该有 conditionrules —— Rule 没有这些属性。

    我们也可以去掉Wrapper,因为它和RuleGroup是一样的。

    这对我有用:

    import com.fasterxml.jackson.annotation.JsonSubTypes;
    import com.fasterxml.jackson.annotation.JsonTypeInfo;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import java.io.IOException;
    import java.util.List;
    
    public class ParseExample {
        static class RuleObject {
        }
    
        static class RuleGroup extends RuleObject {
    
            public String condition;
            @JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
            @JsonSubTypes({
                    @JsonSubTypes.Type(RuleGroup.class),
                    @JsonSubTypes.Type(Rule.class)})
            public List<RuleObject> rules;
        }
    
        static class Rule extends RuleObject{
    
            public String id;
            public String field;
            public String type;
            public String input;
            public String operator;
            public List<String> value;
        }
    
        public static void main(String... args) throws IOException {
            ObjectMapper mapper = new ObjectMapper();
            JsonParser parser = mapper.createParser(ParseExample.class.getClassLoader().getResourceAsStream("test2.json"));
            RuleGroup w = parser.readValueAs(new TypeReference<RuleGroup>() {});
        }
    }
    

    杰克逊版:

          <dependency>
              <groupId>com.fasterxml.jackson.core</groupId>
              <artifactId>jackson-databind</artifactId>
              <version>2.12.4</version>
          </dependency>
    

    结果:

    args = {String[0]@1361} []
    mapper = {ObjectMapper@1362} 
    parser = {UTF8StreamJsonParser@1363} 
    w = {ParseExample$RuleGroup@1364} 
     condition = "AND"
     rules = {ArrayList@1366}  size = 5
      0 = {ParseExample$Rule@1368} 
      1 = {ParseExample$Rule@1369} 
      2 = {ParseExample$Rule@1370} 
      3 = {ParseExample$Rule@1371} 
      4 = {ParseExample$RuleGroup@1372} 
       condition = "AND"
       rules = {ArrayList@1380}  size = 3
        0 = {ParseExample$Rule@1382} 
        1 = {ParseExample$Rule@1383} 
        2 = {ParseExample$RuleGroup@1384} 
         condition = "AND"
         rules = {ArrayList@1386}  size = 1
          0 = {ParseExample$Rule@1388} 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      • 1970-01-01
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      • 2015-04-07
      相关资源
      最近更新 更多