java - JSON/ jackson : Recursive polymorphic deserialization without type field

标签 java json jackson

我目前正在努力解决 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 更复杂、更深入,但结构始终相同:

总是有一个“规则组”,其中包含一个“条件”和一个“规则”列表,规则可以是一个“规则”,也可以是一个“规则组”,深度没有限制,但是我相信它不会比4或5层深。每个级别可以有多个“规则组”

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

Could not resolve subtype of [simple type, class MyClass$AbstractRuleObject]: Cannot deduce unique subtype of MyClass$AbstractRuleObject (2 candidates match)

最佳答案

Rule 和 RuleGroup 没有任何共同点,只是它们都可以出现在列表中,因此 AbstractRuleObject 不应具有 conditionrules其上 - 规则 没有这些属性。

我们也可以摆脱 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>() {});
    }
}

jackson 版本:

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

关于java - JSON/ jackson : Recursive polymorphic deserialization without type field,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68855545/

相关文章:

java - Java 代码中的圈复杂度为 11(最大允许值为 10)

Eclipse 版本 2.1.1 中的 Java EE 透视图

javascript - API JSON 回调问题

javascript - AngularJS 工厂返回 State 对象而不是来自 Promise 的 JSON 数据

jackson - 无法在 Spring Boot 应用程序中注入(inject)多个 ObjectMapper bean

java - 使用 Jackson 将 XML 反序列化为 Java 对象

java - JAX-WS超时问题

java - 如何在java中传递整个类定义

json - 使用自省(introspection)的 Grails JSON 编码导致 Classloader.loadClass() 出现严重瓶颈

json - 如何使用 JPA 和 Hibernate 自动序列化和反序列化 JSON 字符串?