【问题标题】:Serialization of Data Structure with Object References to JSON Using Jackson使用 Jackson 对 JSON 对象引用的数据结构序列化
【发布时间】:2022-10-15 00:29:43
【问题描述】:

我想用 Jackson 2.13.3 将数据结构序列化为 JSON。序列化工作,只是它不按我想要的方式工作。我创建了一个简化的示例数据结构来显示所需的序列化是什么。

数据结构由一个主要的Container 组成,其中包含一个Elements 的列表。这些元素之间有一些联系。

在示例中,我创建了以下元素的链接结构:

startTop <--> endTop
    ^          ^
    |          |
    |          |
    v          v
    startBottom     <-->     endBottom

我想得到以下输出

目标是序列化通过链接信息的 ID 表示链接数据。元素的完整序列化应该只发生在容器的顶级列表中。这与杰克逊在序列化过程中遇到元素的顺序不符。

{
    "allElements": [{
            "id": "startBottom",
            "successor": "endBottom",
            "predecessor": null,
            "upperNeighbours": ["startTop", "endTop"],
            "lowerNeighbours": null
        },
        {
            "id": "endBottom",
            "successor": null,
            "predecessor": "startBottom",
            "upperNeighbours": null,
            "lowerNeighbours": null

        },
        {
            "id": "startTop",
            "successor": "endTop",
            "predecessor": null,
            "upperNeighbours": null,
            "lowerNeighbours": ["startBottom"]
        },
        {
            "id": "endTop",
            "successor": null,
            "predecessor": "startTop",
            "upperNeighbours": null,
            "lowerNeighbours": ["startBottom"]
        }
    ]
}

我确实得到以下输出

jackson 将对象的完整序列化放在它首先遇到对象的任何地方,正如我目前得到的输出所示。

{
  "allElements" : [ {
    "id" : "startBottom",
    "successor" : {
      "id" : "endBottom",
      "successor" : null,
      "predecessor" : "startBottom",
      "upperNeighbours" : null,
      "lowerNeighbours" : null
    },
    "predecessor" : null,
    "upperNeighbours" : [ {
      "id" : "startTop",
      "successor" : {
        "id" : "endTop",
        "successor" : null,
        "predecessor" : "startTop",
        "upperNeighbours" : null,
        "lowerNeighbours" : [ "startBottom" ]
      },
      "predecessor" : null,
      "upperNeighbours" : null,
      "lowerNeighbours" : [ "startBottom" ]
    }, "endTop" ],
    "lowerNeighbours" : null
  }, "endBottom", "startTop", "endTop" ]
}

Process finished with exit code 0

的java代码:

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import java.util.List;

public class Test {
  public static void main(String[] args) throws JsonProcessingException {
    Element startBottom = new Element("startBottom");
    Element endBottom = new Element("endBottom");
    Element startTop = new Element("startTop");
    Element endTop = new Element("endTop");

    startBottom.setSuccessor(endBottom);
    startTop.setSuccessor(endTop);
    endBottom.setPredecessor(startBottom);
    endTop.setPredecessor(startTop);

    startBottom.setUpperNeighbours(List.of(startTop, endTop));
    startTop.setLowerNeighbours(List.of(startBottom));
    endTop.setLowerNeighbours(List.of(startBottom));

    Container container = new Container();
    container.setAllElements(List.of(startBottom, endBottom, startTop, endTop));

    ObjectMapper mapper =
        new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    ObjectWriter prettyPrintWriter = mapper.writerWithDefaultPrettyPrinter();
    System.out.println(prettyPrintWriter.writeValueAsString(container));
  }
}

class Container {
  public List<Element> getAllElements() {return allElements;}
  public void setAllElements(List<Element> allElements) {this.allElements = allElements;}
  private List<Element> allElements;
}

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
    property = "id")
class Element {
  Element(String id) {this.id = id;}

  private String id;

  // May be null
  private Element successor;

  // May be null
  private Element predecessor;

  // May be empty, which for us is the same as being null
  private List<Element> upperNeighbours;

  // May be empty, which for us is the same as being null
  private List<Element> lowerNeighbours;

  public String getId() {return id;}

  public void setId(String id) {this.id = id;}

  public Element getSuccessor() {return successor;}

  public void setSuccessor(Element successor) {this.successor = successor;}

  public Element getPredecessor() {return predecessor;}

  public void setPredecessor(Element predecessor) {this.predecessor = predecessor;}

  public List<Element> getUpperNeighbours() {return upperNeighbours;}

  public void setUpperNeighbours(List<Element> upperNeighbours) {this.upperNeighbours = upperNeighbours;}

  public List<Element> getLowerNeighbours() {return lowerNeighbours;}

  public void setLowerNeighbours(List<Element> lowerNeighbours) {this.lowerNeighbours = lowerNeighbours;}
}

编辑:补充说序列化确实有效,但不是以预期的方式。

【问题讨论】:

  • 序列化不应该那么难,你只需要寻找如何使用successor.id 来获取"successor" 等的值。我很确定有一个注释或属性,但我无法检查atm . (@JsonIdentityInfo 可能是其中一个) - 如果需要,反序列化可能会更难。
  • 你是对的,谢谢!我会投票,但我不能,因为我是新人。

标签: java jackson


【解决方案1】:

只需在您的班级Element 中标记您的成员successorpredecessor,并使用注释@JsonIgnore 来防止死循环。你的代码应该可以工作。但我什至可以提出一些可以让它变得更简单的建议。我编写了自己的实用程序,允许您将任何类序列化为 Json 并将 Json 反序列化回类的实例。它在后台使用 Jackson 库。为您完成这项工作的代码就像这样简单:

try {
  System.out.println(JsonUtils.writeObjectToJsonString(container));
}catch(IOException ioe) {
  //Handle exception
}

其中container 是您的容器类的实例。这是JsonUtils 类的Javadoc。这个类是我编写和维护的 MgntUtils 库的一部分。该库可以通过Maven artifactsGithub获取(包括源代码和Javadoc)

【讨论】:

    【解决方案2】:

    正如@Thomas 评论的那样,我必须在相关字段之前添加:

      @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
          property = "id")
      @JsonIdentityReference(alwaysAsId = true)
    

    然后元素类变为:

    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id")
    class Element {
      Element(String id) {this.id = id;}
    
      private String id;
    
      // May be null
      @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
          property = "id")
      @JsonIdentityReference(alwaysAsId = true)
      private Element successor;
    
      // May be null
      @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
          property = "id")
      @JsonIdentityReference(alwaysAsId = true)
      private Element predecessor;
    
      // May be empty, which for us is the same as being null
      @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
          property = "id")
      @JsonIdentityReference(alwaysAsId = true)
      private List<Element> upperNeighbours;
    
      // May be empty, which for us is the same as being null
      @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
          property = "id")
      @JsonIdentityReference(alwaysAsId = true)
      private List<Element> lowerNeighbours;
    
      public String getId() {return id;}
    
      public void setId(String id) {this.id = id;}
    
      public Element getSuccessor() {return successor;}
    
      public void setSuccessor(Element successor) {this.successor = successor;}
    
      public Element getPredecessor() {return predecessor;}
    
      public void setPredecessor(Element predecessor) {this.predecessor = predecessor;}
    
      public List<Element> getUpperNeighbours() {return upperNeighbours;}
    
      public void setUpperNeighbours(List<Element> upperNeighbours) {this.upperNeighbours = upperNeighbours;}
    
      public List<Element> getLowerNeighbours() {return lowerNeighbours;}
    
      public void setLowerNeighbours(List<Element> lowerNeighbours) {this.lowerNeighbours = lowerNeighbours;}
    }
    

    这(与问题中的其他代码一起)生成所需的输出:

    {
      "allElements" : [ {
        "id" : "startBottom",
        "successor" : "endBottom",
        "predecessor" : null,
        "upperNeighbours" : [ "startTop", "endTop" ],
        "lowerNeighbours" : null
      }, {
        "id" : "endBottom",
        "successor" : null,
        "predecessor" : "startBottom",
        "upperNeighbours" : null,
        "lowerNeighbours" : null
      }, {
        "id" : "startTop",
        "successor" : "endTop",
        "predecessor" : null,
        "upperNeighbours" : null,
        "lowerNeighbours" : [ "startBottom" ]
      }, {
        "id" : "endTop",
        "successor" : null,
        "predecessor" : "startTop",
        "upperNeighbours" : null,
        "lowerNeighbours" : [ "startBottom" ]
      } ]
    }
    

    【讨论】:

      猜你喜欢
      • 2017-12-10
      • 2014-02-12
      • 1970-01-01
      • 2020-07-21
      • 2019-12-01
      • 2019-02-07
      • 2020-08-07
      • 2013-10-06
      • 1970-01-01
      相关资源
      最近更新 更多