使用上下文堆栈而不是使用 JsonIdentityInformation 或 JsonBackReference 和 JsonManagedReference 来处理 Jackson 循环依赖关系



我正在使用Jackson序列化JSON,但我的JSON客户端不是Java,也不使用Jackson。

我想避免循环引用序列化无限递归,每当整个豆类序列化会引起无限的递归,序列化豆的ID而不是整个豆子。

这可以通过维护当前序列化上下文的堆栈来实现。

每当杰克逊开始序列化豆时,它应该查看堆栈是否包含bean。

如果Bean已经在堆栈中,请序列化ID而不是整个Bean,从而避免了无限的递归。

如果豆不在堆栈中,请将其推到堆栈上,并正常序列化整个豆子。

杰克逊(Jackson)序列化豆子后,将豆从堆栈中弹出。

因此,我希望以下Java序列化为以下JSON:

java:

class A {
    String id;
    B      b;
    B      c;
}
class B {
    String id;
    A      a;
}
class Main {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        a.id = "a1";
        b.id = "b1";
        a.b = b;
        a.c = b;
        b.a = a;
        ObjectMapper m = new ObjectMapper();
        System.out.println(m.writeValueAsString(a));
        System.out.println(m.writeValueAsString(b));
    }
}

json:

{
    "id": "a1",
    "b": {
        "id": "b1",
        "a":  "a1"
    },
    "c": {
        "id": "b1",
        "a":  "a1"
    }
}
{
    "id": "b1",
    "a": {
        "id": "a1",
        "b":  "b1"
    }
}

我只知道两种内置杰克逊处理循环引用的方法,如果我正确理解它们,都不能输出上述JSON:

  1. @JsonIdentityInfo,当最好的设置时,请同时注释A& B with:

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

    将输出(带有注释表示问题):

    {
        "id": "a1",
        "b": {
            "id": "b1",
            "a":  "a1"
        },
        "c": "b1" // problem: value of "c" is b.id instead of b with b.a = a.id
    }
    {
        "id": "b1",
        "a": {
            "id": "a1",
            "b":  "b1"
        }
    }
    
  2. @JsonManagedReference&@JsonBackReference,我必须为此指定一侧为前方,而另一侧为背部。说我选择 A-> B属性作为向前的属性,然后得到:

    {
        "id": "a1",
        "b": {
            "id": "b1",
            "a":  "a1"
        },
        "c": {
            "id": "b1",
            "a":  "a1"
        }
    }
    {
        "id": "b1"
        // problem: "a" isn't serialized
    }
    

我想要的是杰克逊的内置方式吗?

如果不是,杰克逊是否保持序列化堆栈?

如果是这样,我该如何访问它,并以某种方式修改序列化输出?

如果不是,我该如何挂接杰克逊在我自己的课堂中维护堆栈,以实现杰克逊接口/扩展一些杰克逊课程,然后使用该堆栈来影响序列化?

杰克逊确实维护了几个堆栈。较旧的是JsonGenerator级别,请参见getOuputContext()。这使您可以看到正在物理上输出的内容,也就是说,范围(对象,数组)是打开的。

但是杰克逊2.5添加了新方法, JsonGenerator.getCurrentValue()和databind的匹配调用,此外,至少在组合两者时,应为您提供序列化的对象图视图。要访问当前价值的祖先,您需要遍历"输出上下文",要求当前价值提高输出堆栈。

相关内容

  • 没有找到相关文章

最新更新