如何解决json序列化程序中休眠双向映射导致的循环引用?

2022-08-31 11:45:19

我正在编写一个序列化程序将POJO序列化为JSON,但陷入了循环引用问题。在休眠双向一对多关系中,父级引用子引用和子引用回父级引用,在这里我的序列化程序死亡。(请参阅下面的示例代码)
如何打破这个循环?我们能否获取对象的所有者树,以查看对象本身是否存在于其所有者层次结构中的某个位置?还有其他方法可以查找引用是否为循环引用?或任何其他想法来解决这个问题?


答案 1

我依靠Google JSON通过使用该功能来处理此类问题

从序列化和反序列化中排除字段

假设 A 类和 B 类之间存在双向关系,如下所示

public class A implements Serializable {

    private B b;

}

和 B

public class B implements Serializable {

    private A a;

}

现在使用 GsonBuilder 获取自定义 Gson 对象,如下所示(注意 setExclusionStrategies 方法)

Gson gson = new GsonBuilder()
    .setExclusionStrategies(new ExclusionStrategy() {

        public boolean shouldSkipClass(Class<?> clazz) {
            return (clazz == B.class);
        }

        /**
          * Custom field exclusion goes here
          */
        public boolean shouldSkipField(FieldAttributes f) {
            return false;
        }

     })
    /**
      * Use serializeNulls method if you want To serialize null values 
      * By default, Gson does not serialize null values
      */
    .serializeNulls()
    .create();

现在我们的循环引用

A a = new A();
B b = new B();

a.setB(b);
b.setA(a);

String json = gson.toJson(a);
System.out.println(json);

看看GsonBuilder


答案 2

Jackson 1.6(2010 年 9 月发布)具有特定的基于注释的支持来处理此类父/子链接,请参阅 http://wiki.fasterxml.com/JacksonFeatureBiDirReferences。(时光倒流快照)

当然,您已经可以使用大多数JSON处理包(jackson,gson和flex-json至少支持它)排除父链接的序列化,但真正的诀窍是如何将其反序列化(重新创建父链接),而不仅仅是处理序列化端。虽然听起来现在只是排除可能对你有用。

编辑(2012 年 4 月):Jackson 2.0 现在支持真实身份参考Wayback Snapshot),因此您也可以通过这种方式解决它。