具有递归结构的Jackson序列化仅打印qNodeId,而不打印其他子节点

qhhrdooz  于 2022-11-08  发布在  其他
关注(0)|答案(1)|浏览(90)

我有3个主要的节点类型如下:节点、CNode、QNode。QNode可以具有CNode的列表,这些CNode可以引用其他CNode,但决不能引用父QNode。QNode是一种节点类型,但具有附加字段,所以它是从最基本的Node节点扩展而来的。2我在将这个结构序列化为JSON和Java对象时遇到了问题。3还有一个TypeInfo类可以有一个可选的Node引用。TypeInfo在QNode中是可选的。当我序列化和打印结果对象时,我只能得到QNode的qNodeId和它的附加属性,而不能得到子节点对象。这是我的尝试。我真的非常感谢关于这个问题的任何帮助,因为我已经在这个问题上做了一段时间,但没有成功
首先输入json示例

{
  "qNodes": [
    {

        "qNodeId": "Q-11122",
        "id": "PO11111",
        "typeInfo": {
          "applicationLevel": "medium",
          "required": true
         },
        "cNodes": [
          {
              "cNodeId": "Q-11155",
              "cNodes": [
                {
                  "qNodeId": "Q-7420",
                  "typeInfo": {
                    "applicationLevel": "low",
                    "assetNode": {
                      "id": "WQ-222",
                      "qNode": {
                        "qNodeId": "Q-0988"
                      }
                    },
                    "required": true
                  },
                  "url": "https://example.com ",
                  "id": "qS111"
                }
              ]
          }
        ]
      }
  ]
}

接下来是Node类

import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import lombok.Data;

    @Data 
    public class Node {
      public String id;
      public QNode qNode;

      @JsonCreator
      public Node(@JsonProperty("qNode") QNode qNode, 
   @JsonProperty("id") String id){
         this.id = id;
         this.qNode = qNode;
     }
   }

下面是QNode类

import com.fasterxml.jackson.annotation.JsonAnySetter;
   import com.fasterxml.jackson.annotation.JsonCreator;
   import com.fasterxml.jackson.annotation.JsonProperty;
   import lombok.Data;

   import java.util.HashMap;
   import java.util.List;
   import java.util.Map;

   @Data
   public class QNode extends BaseNode{
     @JsonProperty("qNodeId")
     private String qNodeId;
     @JsonProperty("cNodes")
     private List<CNode> cNodes;
     private TypeInfo typeInfo;
     private Map<String, String> additionalElements = new HashMap<>();

    @JsonCreator
    public QNode(@JsonProperty("qNode") String qNode,
                 @JsonProperty("id") String id
                 ) {
        super(id);
        this.qNode = qNode;
    }

    @JsonAnySetter
    public void additionalElements(String property, String value) {
        this.additionalElements.put(property, value);
    }
}

下面是CNode类

import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.annotation.JsonProperty;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    public class CNode {
      private String cNodeId;
      private QNode qNode;
      @JsonCreator
      public CNode(@JsonProperty("cNodeId") String cNodeId,@JsonProperty("qNode")QNode 
      qnode){
        this.cNodeId = cNodeId;
        this.qNode = qnode;
    }
}

最后是TypeInfo类

public class TypeInfo {
    public enum Level {
        low,
        medium,
        high;
    }
    private Level applicationLevel;
    private Node assetNode;
    private boolean required;
}

下面是基本节点:

import com.fasterxml.jackson.annotation.JsonAnySetter;
    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import lombok.NoArgsConstructor;

    import java.util.HashMap;
    import java.util.Map;

    @NoArgsConstructor
    public class BaseNode {
    protected String id;
    protected Map<String, String> additionalProperties = new 
    HashMap<>();

    @JsonCreator
    public BaseNode(@JsonProperty("id") String id) {
        this.id = id;

    }

    @JsonAnySetter
    public void additionAnswerProperties(String property, String 
  value) {
        additionalProperties.put(property, value);
    }

  }

下面是收集节点的容器:

import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import lombok.Data;

    import java.util.List;

    @Data
    public class QNodeContainer {
      List<QNode> qNodes;

      @JsonCreator
      public QNodeContainer(@JsonProperty("qNodes") List<QNode> 
 qNodes){
        this.qNodes = qNodes;
    }
 }

下面是我如何把json读进类中的:

File resource2 = new ClassPathResource(
                "data.json").getFile();
        String dataJson = new String(
                Files.readAllBytes(resource2.toPath()));
        ObjectMapper mapper = new 
 ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        QNodeContainer qNodes = mapper.readValue(dataJson, 
               QNodeContainer.class);
vx6bjr1n

vx6bjr1n1#

在应用了一些更改之后,我成功地对您提供的JSON执行了 * 反序列化 * 和后续的 * 序列化 *。
第一条建议:在检查复杂对象图的序列化之前,先看一看较小的部分。当您确定所有自定义类型都可以按预期分别进行 * 序列化/反序列化 * 时,就该检查整个过程了。
以下是我发现的问题:

  • QNode实际上有两个用@JsonAnySetter注解的方法:additionalElements()additionAnswerProperties()继承自BaseNode。这是一个很大的“否-否”,这个注解用于处理所有可以在输入JSON中找到的未Map属性。最多应该有一个这样的注解,应该删除QNodeBaseNode中的这两个Map和方法中的任何一个。2如果出于某种原因需要将这些属性中的一些分离到另一个Map中,则需要在JSON输入中将它们分组到一个特定的定义良好的名称下。
  • 您可能希望使用@JsonAnyGetter注解来展平MapadditionalProperties中包含的数据(我已经应用了它,请注意注解以发现更改)。
  • CNode的JSON表示与您的POJO不一致。有一个JSON数组,而类中的字段是QNode类型(我已经将其更改为List<QNode>)。
  • 缺少一些getter(参见注解)。

这是经过编辑的版本:

@Data
public class Node {
    public String id;
    public QNode qNode;

    @JsonCreator
    public Node(@JsonProperty("qNode") QNode qNode,
                @JsonProperty("id") String id) {
        this.id = id;
        this.qNode = qNode;
    }
}

@Data
public class QNode extends BaseNode {
    @JsonProperty("qNodeId")
    private String qNodeId;
    @JsonProperty("cNodes")
    private List<CNode> cNodes;
    private TypeInfo typeInfo;
//        private Map<String, String> additionalElements = new HashMap<>(); // see the comment above `additionalElements()`

    @JsonCreator
    public QNode(@JsonProperty("qNode") String qNode,
                 @JsonProperty("id") String id
    ) {
        super(id);
        this.qNodeId = qNode; // changed from `this.qNode = qNode;` which raised a compilation error
    }

//        @JsonAnySetter // <- conflicts with @JsonAnySetter on `additionAnswerProperties()` inherited from the super class - there should be only one
//        public void additionalElements(String property, String value) {
//            this.additionalElements.put(property, value);
//        }
}

@JsonInclude(JsonInclude.Include.NON_NULL)
@Getter   // <- added
@ToString // <- added
public class CNode {
    private String cNodeId;
    private List<QNode> qNodes; // <- QNode to List<QNodes>

    @JsonCreator
    public CNode(@JsonProperty("cNodeId") String cNodeId,
                 @JsonProperty("cNodes") List<QNode> qNodes) { // <- "qNode" to "cNodes" & QNode to List<QNodes>
        this.cNodeId = cNodeId;
        this.qNodes = qNodes;
    }
}

@ToString // <- added
@Getter   // <- added
public class TypeInfo {
    private Level applicationLevel;
    private Node assetNode;
    private boolean required;

    public enum Level {
        low,
        medium,
        high;
    }
}

@NoArgsConstructor
public class BaseNode {
    @Getter // <- added
    protected String id;
    @JsonAnyGetter // <- added
    protected Map<String, String> additionalProperties = new HashMap<>();

    @JsonCreator
    public BaseNode(@JsonProperty("id") String id) {
        this.id = id;
    }

    @JsonAnySetter
    public void additionAnswerProperties(String property, String value) {
        additionalProperties.put(property, value);
    }
}

@Data
public class QNodeContainer {
    private List<QNode> qNodes;

    @JsonCreator
    public QNodeContainer(@JsonProperty("qNodes") List<QNode> qNodes) {
        this.qNodes = qNodes;
    }
}

演示问题中提供的JSON示例的 * 反序列化/序列化 * 的代码:

String json = """
    past your JSON here
    """;

ObjectMapper mapper = new ObjectMapper()
    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

QNodeContainer qNodes = mapper.readValue(json, QNodeContainer.class);

System.out.println(qNodes);

System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(qNodes));

指定的JSON表示和Java类之间差异的图示:

相关问题