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

时间:2011-03-17 22:17:27

标签: json hibernate spring many-to-many circular-reference

我正在尝试将POJO序列化为JSON,但却陷入循环引用问题。我知道如何使用@JsonBackReference@JsonManagedReference处理一对多和反向关系。

我的问题是双向的多对多关系(例如,一个学生可以有很多课程,每个课程可以有很多学生注册),父母参考儿童和孩子参考回到父母,这里我的序列化器死了。根据我的理解,我不能在这里使用@JsonBackReference,因为属性的值类型必须是bean:它不能是Collection,Map,Array或枚举。

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

5 个答案:

答案 0 :(得分:9)

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

答案 1 :(得分:2)

由于@Bozho回答使用@JsonIgnoreProperties,试试这个,它对我有用。

以下是我的@JsonIgnoreProperties模型:

@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(相关)模型的集合类型属性。

答案 2 :(得分:0)

您还可以使用Dozer映射将POJO转换为Map并排除字段。例如,如果我们有两个类PojoA和PojoB具有双向关系,我们定义像这样的映射

<mapping map-id="mapA" map-null="false">
  <class-a>com.example.PojoA</class-a>
  <class-b>java.util.Map</class-b>
  <field>
    <a>fieldA</a>
    <b>this</b>
  </field>  
  <field map-id="mapB">
      <a>pojoB</a>
      <b>this</b>
      <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>
    <a>pojoA</a>
    <b>this</b>
  </field-exclude>
</mapping>

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

<bean id="mapper" class="org.dozer.DozerBeanMapper">
   <property name="mappingFiles">
    <list>
       <value>dozerMapping.xml</value>
    </list>
   </property>
</bean>

然后在你序列化的课程中

public class TestClass
{
     @Autowired
     DozerBeanMapper mapper;

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

Dozer manual here

答案 3 :(得分:0)

阐述@Bozho已经提到的内容......

我现在因为我正在使用Google Cloud Endpoints而遇到了Jackson 1,因此即使Jackson 2已经出局一段时间,这仍然可以帮助一些人。即使我不需要反序列化整个对象,仍然非常需要引用。

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

@JsonIgnore
private FooClass foo;

public String getFooKey()
...

使用Cloud Endpoints,这会导致在GET有效负载中返回一个扁平的“fooKey”,同时省略“foo”。

答案 4 :(得分:-1)

如果您有集合对象,请将其设为

collection<object> listobj 

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

这应该工作,你现在得到的对象可以是json序列化和干净的