java - 杰克逊与建设者模式和反向参考
问题描述
我现在不太清楚如何制定我的标题,但是我遇到了我正在处理的代码的问题,我只能通过示例来解释,所以就这样吧。
我有一个嵌套的对象结构,当它发生变化时我会坚持归档。这是模型的要点:
@JsonDeserialize(builder = Parent.Builder.class)
public class Parent {
private String id;
private List<Child> children;
private Parent(Builder builder) {
id = builder.id;
children = builder.children;
setParentChildRelationship();
}
private void setParentChildRelationship() {
children.forEach(c -> c.setParent(this));
}
public String getId() {
return id;
}
public List<Child> getChildren() {
return children;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String id;
private List<Child> children = Collections.emptyList();
private Builder() {
}
public Builder withId(final String id) {
this.id = id;
return this;
}
public Builder withChildren(final List<Child> children) {
this.children = children;
return this;
}
public Parent build() {
return new Parent(this);
}
}
}
@JsonDeserialize(builder = Child.Builder.class)
public class Child {
private String id;
@JsonBackReference
private Parent parent;
private Child(Builder builder) {
id = builder.id;
}
public String getId() {
return id;
}
public Parent getParent() {
return parent;
}
public static Builder builder() {
return new Builder();
}
public void setParent(final Parent parent) {
this.parent = parent;
}
public static class Builder {
private String id;
private Builder() {
}
public Builder withId(final String id) {
this.id = id;
return this;
}
public Child build() {
return new Child(this);
}
}
}
然后我可以很好地序列化它:
@Test
void serialize() throws JsonProcessingException {
final Parent parent = Parent.builder()
.withId("1")
.withChildren(List.of(Child.builder()
.withId("2")
.build()))
.build();
System.out.println(parent.getChildren().get(0).getParent().getId());
System.out.println(JSONUtil.toPrettyJSON(parent));
}
上面的测试输出一个1
和以下 JSON 结构:
{
"id": "1",
"children": [{
"id": "2"
}]
}
我也可以将它反序列化到我的父类中,这个测试输出与上面的测试相同。
@Test
void deserialize() throws JsonProcessingException {
final String json = "{\"id\":\"1\",\"children\":[{\"id\":\"2\"}]}";
final Parent parent = JSONUtil.fromString(json, Parent.class);
System.out.println(parent.getChildren().get(0).getParent().getId());
System.out.println(JSONUtil.toPrettyJSON(parent));
}
一旦反序列化,我一直努力保持这个状态不可变,但我现在需要修改一个孩子(听起来很可怕),所以我toBuilder()
在孩子身上引入了一种方法:
public Builder toBuilder() {
return new Builder().withId(id);
}
我像这样使用它:
@Test
void modify_child() {
final Parent parent = Parent.builder()
.withId("1")
.withChildren(List.of(Child.builder()
.withId("2")
.build()))
.build();
final Child modifiedChild = parent.getChildren().get(0).toBuilder().withId("3").build();
System.out.println(modifiedChild.getParent());
}
这个测试的输出当然是null
,因为我不维护对 parent 的引用,因为它不是构建器的一部分。
如何在允许修改子代的同时改进我的模式并保持父子关系?
这是使用杰克逊解决的,还是简单地以更合适的方式处理修改?
解决方案
推荐阅读
- logging - pod 中的 Kubernetes 日志位置
- asp.net - 更新 API 后 IIS 上出现错误 404
- spring-mvc - 如何在 Spring 组件类中访问 HttpServletRequest
- angular - agm-map 动态显示/更新标记不起作用
- html - Bootstrap 4 img-fluid:如何在轮播中为移动设备上的图像制作一致的高度
- python - 使用 Python 压缩和格式化添加到 Word 文档中的照片
- json.net - Json.Net - 匿名类型的部分反序列化
- javascript - 选择第二个孩子并赋予 ID - Javascript
- dart - Dart:使用 Observatory 查找内存泄漏
- outlook-addin - 在 Outlook 中,如何在单独的窗口中关闭消息?