如何解决json序列化器中的循环引用由多个TO多个hibernate双向映射引起的?

How to solve circular reference in json serializer caused by Many TO Many hibernate bidirectional mapping?

我试图将pojo序列化为json,但陷入了循环引用问题。我知道如何使用@JsonBackReference@JsonManagedReference处理一对多和反向关系。

我的问题是双向多对多关系(例如,一个学生可以有许多课程,每个课程可以有许多学生注册),家长引用子引用回父引用,而在这里,我的序列化程序就死了。根据我的理解,这里不能使用@JsonBackReference作为属性的值类型必须是bean:它不能是集合、映射、数组或枚举。

有人能告诉我如何处理这种情况吗?


您可以在关系的一侧使用@JsonIgnoreProperties("someField")(注释是类级的)。或@JsonIgnore


正如@bozho回答使用@jsonignoreproperties一样,试试这个,它对我很有用。

以下是我的@jsonignoreproperties模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Entity
public class Employee implements Serializable{
    @ManyToMany(fetch=`enter code here`FetchType.LAZY)
    @JoinTable(name="edm_emp_dept_mappg",
        joinColumns={@JoinColumn(name="emp_id", referencedColumnName="id")},
        inverseJoinColumns={@JoinColumn(name="dept_id", referencedColumnName="id")})
    @JsonIgnoreProperties(value="employee")
    Set<Department> department = new HashSet<Department>();
}


@Entity
public class Department implements Serializable {
    @ManyToMany(fetch=FetchType.LAZY, mappedBy="department")
    @JsonIgnoreProperties(value="department")
    Set<Employee> employee = new HashSet<Employee>();
}

在@jsonignoreproperties的value属性中,我们需要提供counter(relevant)模型的collection type属性。


正在阐述@bozho已经提到的内容…

我现在和Jackson1在一起是因为我使用的是GoogleCloudEndpoints,所以即使Jackson2已经退出了一段时间,这可能仍然对一些人有帮助。尽管我不需要对整个对象进行反序列化,但是引用仍然是非常必要的。

我将@jsonignore放在产生循环引用的字段上,但随后为每个字段创建了一个新的getter,以便在我的API中仍然返回一个平面引用。

1
2
3
4
5
@JsonIgnore
private FooClass foo;

public String getFooKey()
...

对于云端点,这会导致在get有效负载中返回一个平坦的"fookey",而忽略了"foo"。


您还可以使用推土机映射将POJO转换为映射并排除字段。例如,如果我们有两个类pojoa和pojob具有双向关系,那么我们就这样定义映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<mapping map-id="mapA" map-null="false">
  <class-a>com.example.PojoA</class-a>
  <class-b>java.util.Map</class-b>
  <field>
    fieldA
    this
  </field>  
  <field map-id="mapB">
      pojoB
      this
      <b-hint>java.util.Map</b-hint>
  </field>
</mapping>

<mapping map-id="mapB" map-null="false">
  <class-a>com.example.PojoB</class-a>
  <class-b>java.util.Map</class-b>
  <field-exclude>
    pojoA
    this
  </field-exclude>
</mapping>

然后定义一个bean,将上面的推土机映射文件设置为一个属性。

1
2
3
4
5
6
7
<bean id="mapper" class="org.dozer.DozerBeanMapper">
   <property name="mappingFiles">
    <list>
       <value>dozerMapping.xml</value>
    </list>
   </property>
</bean>

然后在你要序列化的类中

1
2
3
4
5
6
7
8
9
10
public class TestClass
{
     @Autowired
     DozerBeanMapper mapper;

     public Map<String,Object> serializeObject(PojoA pojoA)
     {
          return ((Map<String, Object>) mapper.map(pojoA, Map.class,"mapA"));
     }
}

这里是推土机手册。


如果你有集合对象,就让它

1
2
3
4
5
6
7
8
collection<object> listobj

var jsonObj = from c in listobj
                  select new
                 {
                   Prop1 = c.Prop1
                    ...
                 }

这应该可以工作,您现在得到的对象可以是JSON序列化的,并且它是干净的。