Как решить круговую ссылку в сериализаторе json, вызванную двунаправленным отображением Many TO Many в спящем режиме?

Я пытаюсь сериализовать POJO в JSON, но застрял в проблеме с круговой ссылкой. Я знаю, как работать с отношениями "один ко многим" и наоборот, используя @JsonBackReference и @JsonManagedReference.

Моя проблема связана с двунаправленным отношением «многие ко многим» (например, у студента может быть много курсов, и на каждый курс может быть зачислено много студентов), родительские ссылки на дочерние и дочерние ссылки обратно на родительский, и здесь мой сериализатор умирает. Насколько я понимаю, я не могу использовать здесь @JsonBackReference, поскольку тип значения свойства должен быть bean-компонентом: он не может быть коллекцией, картой, массивом или перечислением.

Может кто-нибудь посоветовать, как я могу справиться с этим сценарием?


person M.Rather    schedule 17.03.2011    source источник


Ответы (5)


Вы можете использовать @JsonIgnoreProperties("someField") на одной из сторон отношений (аннотация на уровне класса). Или @JsonIgnore

person Bozho    schedule 17.03.2011
comment
Это, а также некоторые дополнения, о которых я упомяну ниже, довольно хорошо решили для меня аналогичную проблему. - person John Michelau; 12.11.2013

Поскольку @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>();
}

В атрибуте value @JsonIgnoreProperties нам необходимо предоставить свойство типа коллекции модели счетчика (связанной).

person udit khare    schedule 20.01.2016
comment
Хороший ответ, но я бы исправил fetch='enter code here, и было бы проще использовать множественное число для свойств: departments и employees. - person PJ_Finnegan; 27.05.2021

Вы также можете использовать сопоставление Dozer для преобразования POJO в карту и исключения полей. Например, если у нас есть два класса 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 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"));
     }
}

Руководство для бульдозера здесь.

person Prasanna    schedule 18.03.2011

Излагая то, что уже упоминал @Bozho ...

Я застрял с Jackson 1 прямо сейчас, потому что я использую конечные точки Google Cloud, так что это все еще может помочь некоторым людям, хотя Jackson 2 уже давно отсутствует. Несмотря на то, что мне не нужна десериализация всего объекта, ссылка все равно очень необходима.

Я поместил @JsonIgnore в поля, вызывающие циклическую ссылку, но затем создал новый метод получения для каждого из них, чтобы плоская ссылка по-прежнему возвращалась в моих API.

@JsonIgnore
private FooClass foo;

public String getFooKey()
...

В случае с Cloud Endpoints это приводит к тому, что в полезных данных GET возвращается плоский «fooKey» без «foo».

person John Michelau    schedule 11.11.2013

если у вас есть объект коллекции, пусть это будет

collection<object> listobj 

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

Это должно работать, и объект, который вы сейчас получаете, может быть сериализован json и его чистым

person Praneeth    schedule 17.03.2011