具有递归结构的jackson序列化

时间:2016-12-07 14:41:05

标签: java data-structures tree jackson

我有这个由杰克逊序列化的java模型:

@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="orderId")
public class ClonedOrder extends ResourceSupport implements Serializable{
    private long orderId;
    private ClonedOrder parent;
    private List<ClonedOrder> children = new ArrayList<>();

    @JsonProperty("root")
    public ClonedOrder root() {
        if (parent == null) {
            return this;
        } else {
            return parent.root();
        }
    }

当杰克逊序列化这棵树时,响应如下:

{
  "orderId": 163811134,
  "parent": {
    "orderId": 153684020,
    "parent": null,
    "children": [],
    "root": 153684020
  },
  "children": [
   {
     "orderId": 163811135,
     "parent": 163811134,
     "children": [],
     "root": 153684020
   },
  "root": 153684020
}

问题是ClonedOrder类型的根节点没有序列化为ClonedOrder(带有父节点,子节点和根节点),但只有id作为long类型。

问题是我不能使用相同的模型进行序列化和反序列化,因为json从服务器更改为客户端。

知道如何实现这一目标吗?

2 个答案:

答案 0 :(得分:1)

正如您之前注意到的那样,使用JsonIdentityInfo jackson只是序列化long orderId并跳过标准的java对象序列化以避免无限的嵌套对象(意味着堆栈溢出)。

我建议使用更简单的数据结构序列化所需的所有数据,例如用于将这些数据存储在关系数据库中的模型。我弄清楚的模型是:

relations: [
    {"id": 163811134, "parent": 153684020},
    {"id": 163811135, "parent": 163811134},
    {"id": 153684020, "parent": null},
]

使用这种结构,使用实用程序方法找到所需内容非常简单:

private class CloningRelations {
    List<CloningOrder> orders;

    public Long getRoot(){
        for (CloningOrder o : orders)
            if (o.getParent() != null)
                return o.getId();
        return null;
    }

    @JsonIgnore public List<Long> getChildrenOf(long id) {
        ArrayList<Long> list = new ArrayList<>();
        for (CloningOrder o : orders)
            if (o.getParent() == id)
                list.add(o.getId());
        return list;
    }

    @JsonIgnore public List<Long> getDescendantsOf(long id) {
        ArrayList<Long> list = new ArrayList<>();
        for (CloningOrder o : orders)
            if (o.getParent() == id) {
                list.add(o.getId());
                list.addAll(getDescendantsOf(o.getId()));
            }
        return list;
    }

    @JsonIgnore public Long getParentOf(long id) {
        for (CloningOrder o : orders)
            if (o.getId() == id)
                return o.getParent();
        return null;
    }

    @JsonIgnore public List<Long> getAncestorsOf(long id) {
        ArrayList<Long> list = new ArrayList<>();
        for (CloningOrder o : orders)
            if (o.getId() == id) {
                list.add(o.getParent()); //sorted too!
                list.addAll(getAncestorsOf(o.getParent()));
            }
        return list;
    }

    private class CloningOrder {
        long id;
        Long parent;

        public long getId() {
            return id;
        }

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

        public Long getParent() {
            return parent;
        }

        public void setParent(Long parent) {
            this.parent = parent;
        }

    }
}

答案 1 :(得分:1)

您可以使用两个注释@JsonManagedReference@JsonBackReference来处理双向引用。

看看here