9

I am trying to serialize POJO to JSON but stuck in circular reference problem. I know how to handle one to many and reverse relationships using the @JsonBackReference and @JsonManagedReference.

My problem is with bidirectional many-to-many relation(eg a student can have many courses and each course can have many students enrolled), parent references child and child references back to parent and here my serializer dies. As per my understanding I cannot use @JsonBackReference here as value type of the property must be a bean: it can not be a Collection, Map, Array or enumeration.

Can some one please advise how I can handle this scenario?

skaffman
  • 398,947
  • 96
  • 818
  • 769
M.Rather
  • 101
  • 2
  • 3

5 Answers5

9

You can use @JsonIgnoreProperties("someField") on one of the sides of the relations (the annotation is class-level). Or @JsonIgnore

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
3

As @Bozho have answered to use @JsonIgnoreProperties, try this, it worked for me.

Below are my models with @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>();
}

In value attribute of @JsonIgnoreProperties, we need to provide the collection type property of counter(related) model.

udit khare
  • 354
  • 2
  • 10
  • Nice answer but I'd fix `fetch='enter code here` and it would be clearer to use the plurals for properties: `departments` and `employees`. – PJ_Finnegan May 27 '21 at 07:52
0

Expounding on what @Bozho already mentioned...

I'm stuck with Jackson 1 right now because I'm using Google Cloud Endpoints, so this might still help some people even though Jackson 2 has been out for a while. Even though I don't need the whole object deserialized, the reference is still very necessary.

I put @JsonIgnore on the fields causing the circular reference, but then created a new getter for each one so that a flat reference is still returned in my APIs.

@JsonIgnore
private FooClass foo;

public String getFooKey()
...

With Cloud Endpoints, this results in a flat "fooKey" being returned in the GET payload, while omitting "foo".

John Michelau
  • 1,001
  • 8
  • 12
0

You can also use Dozer mapping to convert a POJO to a Map and exclude fields. For example if we have two classes PojoA and PojoB having bi-directional relationships, we define mapping like this

<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>

Then you define a bean setting the above dozer mapping file as a property.

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

Then in the class that where you are serializing

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.

Prasanna
  • 3,703
  • 9
  • 46
  • 74
-1

if you have the collection object let it be

collection<object> listobj 

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

This should work and object you get now can be json serialized and its clean

Praneeth
  • 2,527
  • 5
  • 30
  • 47