java - 识别、分组和处理对象总是由 id 单独序列化
问题描述
以下设置在 Java 11 上运行 jackson-databind (v 2.10.3)。
我有以下示例类来展示我的情况:Root、Trunk Leaf。它们有一些来回引用,语义可以忽略。
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
scope = Root.class,
property = "id")
public class Root {
@JsonProperty
private String id;
@JsonProperty
@JsonIdentityReference(alwaysAsId = true) // Marker1
private List<Trunk> trunks;
public Root() {
}
public Root(
String id,
List<Trunk> trunks) {
this.id = id;
this.trunks = trunks;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Trunk> getTrunks() {
return trunks;
}
public void setTrunks(List<Trunk> trunks) {
this.trunks = trunks;
}
}
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
scope = Trunk.class,
property = "id2")
//@JsonIdentityReference
public class Trunk {
@JsonProperty
private String id2;
@JsonProperty
@JsonIdentityReference(alwaysAsId = true)
private Root backRoot;
@JsonIdentityReference(alwaysAsId = true)
@JsonProperty
private Trunk next;
@JsonProperty
@JsonIdentityReference(alwaysAsId = true)
private Leaf leaf;
public Trunk() {
}
public Trunk(
String id2) {
this.id2 = id2;
}
public Root getBackRoot() {
return backRoot;
}
public void setBackRoot(Root backRoot) {
this.backRoot = backRoot;
}
public Trunk getNext() {
return next;
}
public void setNext(Trunk next) {
this.next = next;
}
public Leaf getLeaf() {
return leaf;
}
public void setLeaf(Leaf leaf) {
this.leaf = leaf;
}
}
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
scope = Leaf.class,
property = "id")
public class Leaf {
@JsonProperty
private String id;
@JsonProperty
private String content;
public Leaf() {}
public Leaf(String id, String content) {
this.id = id;
this.content = content;
}
}
目标是序列化(然后反序列化)对象图,注意有循环和引用多次出现。例如:
var trunk1 = new Trunk("A");
var trunk2 = new Trunk("N2");
var leaf = new Leaf("LA", "38!");
trunk1.setLeaf(leaf);
trunk2.setLeaf(leaf);
var test = new Root("A", List.of(trunk1, trunk2));
trunk1.setBackRoot(test);
trunk1.setNext(trunk2);
trunk2.setBackRoot(test);
trunk2.setNext(trunk2);
String resultObjAsString = new ObjectMapper().writeValueAsString(test);
在当前设置中 resultObjAsString 等于(如预期){"id":"A","trunks":["A","N2"]}
:。如果我删除 Marker1 处的行,则 resultObjAsString 等于
{
"id": "A",
"trunks": [
{
"id2": "A",
"backRoot": "A",
"next": "N2",
"leaf": "LA"
},
{
"id2": "N2",
"backRoot": "A",
"next": "N2",
"leaf": "LA"
}
]
}
正如预期的那样。正如 JsonIdentityReference 的 JavaDoc 中的注释告诉我们“反序列化可能需要额外的上下文信息”,即上述输出的反序列化当然不能恢复原始对象图。我不确定我的选择是什么。
我打算创建的是以下“标准化”输出:
{
"root": {
"A": {
"id": "A",
"trunks": [
"A",
"N2"
]
}
},
"trunk": {
"A": {
"id2": "A",
"backRoot": "A",
"next": "N2",
"leaf": "LA"
},
"N2": {
"id2": "N2",
"backRoot": "A",
"next": "N2",
"leaf": "LA"
}
},
"leaf": {
"LA": {
"id": "LA",
"content": "38!"
}
}
}
这意味着,虽然每个相关引用都与alwaysAsId=true
上下文一起存储,但不会丢失,而是存储在输出的顶层。
我知道用jackson本地创建输出可能是不可能的,但我希望有一种方法可以访问所有作为引用存储的对象,以便以后枚举和单独存储它们的内容并编译总序列化输出。相反,我还需要一种向相关反序列化器提供反序列化对象的方法。
解决方案
推荐阅读
- c# - 如何使用用户选择的背景颜色覆盖图标的默认背景?
- angular - 无法将 Angular 自定义元素与其他 Angular 应用程序一起使用
- java - 打印带有条件的二维数组
- c++ - 无法理解 ns-3 源代码中 getter 方法的 Constructor() 语法
- laravel - 未找到列:1054 未知列“where 子句”中的“orders.deleted_at”
- odoo - Odoo - odoo 配置文件中的 xmlrc_port 和 http_port 参数有什么区别?
- c++ - 如何将 CLI 类的函数指针作为参数传递给 C++ 方法
- ruby-on-rails - gem安装权限问题
- javascript - 无法将 javascript 链接到 html 文件?
- reactjs - 将 Material UI react-autosuggest 功能转换为基于类组件