处理Jackson亲子序列化(Handling Jackson Parent

编程入门 行业动态 更新时间:2024-10-27 22:22:45
处理Jackson亲子序列化(Handling Jackson Parent-Child Serialization)

我正在使用Spring MVC(我是新手),Hibernate和Jackson用于我的项目,并使用JSON进行服务器和客户端之间的数据交换。

我有几个类“Employee”和“Address”与ManyToOne / OneToMany关系。

我遇到了循环引用错误,但是,我能够使用@JsonManagedReference和@JsonBackReference解决这个问题。

但问题是,在序列化期间(我正在查询数据库以获取所有员工),Jackson完全忽略了Address属性并仅序列化了3个字段(其他字段已被忽略,您可以在代码中看到)。

这是返回的JSON

[ { "id": 1, "name": "xxx", "age": 100 }, { "id": 2, "name": "yyy", "age": 100 } ]

员工类:

@Entity @Table(name = "e_employee", catalog = "emploman") public class Employee implements java.io.Serializable { private int id; private String name; private int age; private Address address; private String modifiedBy; private Date modifiedTime; private transient int addressId; public Employee() { } public Employee(int id, String name, int age, Address address, String modifiedBy, Date modifiedTime) { this.id = id; this.name = name; this.age = age; this.address = address; this.modifiedBy = modifiedBy; this.modifiedTime = modifiedTime; } public Employee(String name, int age, Address address, String modifiedBy, Date modifiedTime) { this.name = name; this.age = age; this.address = address; this.modifiedBy = modifiedBy; this.modifiedTime = modifiedTime; } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", unique = true, nullable = false) public int getId() { return id; } public void setId(int id) { this.id = id; } @Column(name = "name", nullable = false, length = 100) public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(name = "age", nullable = false) public int getAge() { return age; } public void setAge(int age) { this.age = age; } @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "address", nullable = false) @JsonBackReference("employee-address") public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Column(name = "modified_by", nullable = false, length = 50) @JsonIgnore public String getModifiedBy() { return modifiedBy; } @JsonIgnore public void setModifiedBy(String modifiedBy) { this.modifiedBy = modifiedBy; } @Temporal(TemporalType.TIMESTAMP) @Column(name = "modified_time", nullable = false, length = 19) @JsonIgnore public Date getModifiedTime() { return modifiedTime; } @JsonIgnore public void setModifiedTime(Date modifiedTime) { this.modifiedTime = modifiedTime; } @JsonIgnore @Transient public int getAddressId() { return addressId; } @JsonIgnore public void setAddressId(int addressId) { this.addressId = addressId; } }

地址类:

@Entity @Table(name = "e_address", catalog = "emploman") public class Address implements java.io.Serializable { private int id; private String country; private String state; private String city; private String streetAddress; private String pinCode; private String modifiedBy; private Date modifiedTime; private Set<Employee> employees; public Address() { } public Address(int id, String country, String state, String city, String streetAddress, String pinCode, String modifiedBy, Date modifiedTime, Set<Employee> employees) { this.id = id; this.country = country; this.state = state; this.city = city; this.streetAddress = streetAddress; this.pinCode = pinCode; this.modifiedBy = modifiedBy; this.modifiedTime = modifiedTime; this.employees = employees; } public Address(String country, String state, String city, String streetAddress, String pinCode, String modifiedBy, Date modifiedTime, Set<Employee> employees) { this.country = country; this.state = state; this.city = city; this.streetAddress = streetAddress; this.pinCode = pinCode; this.modifiedBy = modifiedBy; this.modifiedTime = modifiedTime; this.employees = employees; } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") public int getId() { return id; } public void setId(int id) { this.id = id; } @Column(name = "country", nullable = false, length = 100) public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } @Column(name = "state", nullable = false, length = 100) public String getState() { return state; } public void setState(String state) { this.state = state; } @Column(name = "city", nullable = false, length = 100) public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Column(name = "street_address", nullable = false, length = 500) public String getStreetAddress() { return streetAddress; } public void setStreetAddress(String streetAddress) { this.streetAddress = streetAddress; } @Column(name = "pincode", nullable = false, length = 15) public String getPinCode() { return pinCode; } public void setPinCode(String pinCode) { this.pinCode = pinCode; } @Column(name = "modified_by", nullable = false, length = 50) public String getModifiedBy() { return modifiedBy; } public void setModifiedBy(String modifiedBy) { this.modifiedBy = modifiedBy; } @Temporal(TemporalType.TIMESTAMP) @Column(name = "modified_time", nullable = false, length = 19) public Date getModifiedTime() { return modifiedTime; } public void setModifiedTime(Date modifiedTime) { this.modifiedTime = modifiedTime; } @OneToMany(mappedBy = "address", fetch = FetchType.LAZY) @JsonManagedReference(value = "employee-address") public Set<Employee> getEmployees() { return employees; } public void setEmployees(Set<Employee> employees) { this.employees = employees; } }

所以,基本上,我期待的json响应如下所示:

[ { "id": 1, "name": "xxx", "age": 100, "address": { "country": "xxx", "city": "abc" } } ]

有人可以帮忙吗?

更新1

我尝试从数据库中获取地址,并且成功获取与该地址相关的员工

[ { "id": 1, "country": "xxx", "state": "yyy", "city": "zzz", "streetAddress": "abc", "pinCode": "12345", "modifiedBy": "xxx", "modifiedTime": 1400930509000, "employees": [ { "id": 2, "name": "xxx", "age": 190 }, { "id": 1, "name": "xxx", "age": 200 } ] } ]

I'm using Spring MVC (am new to this), Hibernate and Jackson for my project and am using JSON for data exchange between the server and client.

I have a couple of classes "Employee" and "Address" with a ManyToOne / OneToMany relationship.

I faced the cyclic reference error, however, I was able to resolve that using @JsonManagedReference and @JsonBackReference.

But the problem is, during serialization (I'm querying the DB to get all the employees), Jackson is completely ignoring the Address property and serializing just 3 fields (other fields have been ignored specifically which you can see in the code).

Here's the JSON returned

[ { "id": 1, "name": "xxx", "age": 100 }, { "id": 2, "name": "yyy", "age": 100 } ]

The Employee Class:

@Entity @Table(name = "e_employee", catalog = "emploman") public class Employee implements java.io.Serializable { private int id; private String name; private int age; private Address address; private String modifiedBy; private Date modifiedTime; private transient int addressId; public Employee() { } public Employee(int id, String name, int age, Address address, String modifiedBy, Date modifiedTime) { this.id = id; this.name = name; this.age = age; this.address = address; this.modifiedBy = modifiedBy; this.modifiedTime = modifiedTime; } public Employee(String name, int age, Address address, String modifiedBy, Date modifiedTime) { this.name = name; this.age = age; this.address = address; this.modifiedBy = modifiedBy; this.modifiedTime = modifiedTime; } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", unique = true, nullable = false) public int getId() { return id; } public void setId(int id) { this.id = id; } @Column(name = "name", nullable = false, length = 100) public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(name = "age", nullable = false) public int getAge() { return age; } public void setAge(int age) { this.age = age; } @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "address", nullable = false) @JsonBackReference("employee-address") public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } @Column(name = "modified_by", nullable = false, length = 50) @JsonIgnore public String getModifiedBy() { return modifiedBy; } @JsonIgnore public void setModifiedBy(String modifiedBy) { this.modifiedBy = modifiedBy; } @Temporal(TemporalType.TIMESTAMP) @Column(name = "modified_time", nullable = false, length = 19) @JsonIgnore public Date getModifiedTime() { return modifiedTime; } @JsonIgnore public void setModifiedTime(Date modifiedTime) { this.modifiedTime = modifiedTime; } @JsonIgnore @Transient public int getAddressId() { return addressId; } @JsonIgnore public void setAddressId(int addressId) { this.addressId = addressId; } }

The Address Class:

@Entity @Table(name = "e_address", catalog = "emploman") public class Address implements java.io.Serializable { private int id; private String country; private String state; private String city; private String streetAddress; private String pinCode; private String modifiedBy; private Date modifiedTime; private Set<Employee> employees; public Address() { } public Address(int id, String country, String state, String city, String streetAddress, String pinCode, String modifiedBy, Date modifiedTime, Set<Employee> employees) { this.id = id; this.country = country; this.state = state; this.city = city; this.streetAddress = streetAddress; this.pinCode = pinCode; this.modifiedBy = modifiedBy; this.modifiedTime = modifiedTime; this.employees = employees; } public Address(String country, String state, String city, String streetAddress, String pinCode, String modifiedBy, Date modifiedTime, Set<Employee> employees) { this.country = country; this.state = state; this.city = city; this.streetAddress = streetAddress; this.pinCode = pinCode; this.modifiedBy = modifiedBy; this.modifiedTime = modifiedTime; this.employees = employees; } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") public int getId() { return id; } public void setId(int id) { this.id = id; } @Column(name = "country", nullable = false, length = 100) public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } @Column(name = "state", nullable = false, length = 100) public String getState() { return state; } public void setState(String state) { this.state = state; } @Column(name = "city", nullable = false, length = 100) public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Column(name = "street_address", nullable = false, length = 500) public String getStreetAddress() { return streetAddress; } public void setStreetAddress(String streetAddress) { this.streetAddress = streetAddress; } @Column(name = "pincode", nullable = false, length = 15) public String getPinCode() { return pinCode; } public void setPinCode(String pinCode) { this.pinCode = pinCode; } @Column(name = "modified_by", nullable = false, length = 50) public String getModifiedBy() { return modifiedBy; } public void setModifiedBy(String modifiedBy) { this.modifiedBy = modifiedBy; } @Temporal(TemporalType.TIMESTAMP) @Column(name = "modified_time", nullable = false, length = 19) public Date getModifiedTime() { return modifiedTime; } public void setModifiedTime(Date modifiedTime) { this.modifiedTime = modifiedTime; } @OneToMany(mappedBy = "address", fetch = FetchType.LAZY) @JsonManagedReference(value = "employee-address") public Set<Employee> getEmployees() { return employees; } public void setEmployees(Set<Employee> employees) { this.employees = employees; } }

So, basically, the json response I'm expecting is something like below:

[ { "id": 1, "name": "xxx", "age": 100, "address": { "country": "xxx", "city": "abc" } } ]

Could anyone please help?

Update 1

I've tried getting Addresses from the DB, and employees related to that address is successfully being fetched

[ { "id": 1, "country": "xxx", "state": "yyy", "city": "zzz", "streetAddress": "abc", "pinCode": "12345", "modifiedBy": "xxx", "modifiedTime": 1400930509000, "employees": [ { "id": 2, "name": "xxx", "age": 190 }, { "id": 1, "name": "xxx", "age": 200 } ] } ]

最满意答案

谢谢大家。

我能够通过在我的类(父类和子类)上使用JsonIdentityInfo以及一个名为jackson-datatype-hibernate的插件来解决此问题,通过该插件我启用了一个名为FORCE_LAZY_LOADING的功能

如果它对任何人有帮助,下面是上述配置的代码:

创建一个类,如下所示,启用jackson-datatype-hibernate

public class HibernateAwareObjectMapper extends ObjectMapper { public HibernateAwareObjectMapper() { Hibernate4Module hbm = new Hibernate4Module(); hbm.enable(Hibernate4Module.Feature.FORCE_LAZY_LOADING); registerModule(hbm); } }

告诉Spring使用上面的ObjectMapper而不是Jackson提供的默认值:

<mvc:annotation-driven> <mvc:message-converters> <!-- Use the HibernateAware mapper instead of the default --> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="com.adwitiya.o2plus.utilities.HibernateAwareObjectMapper" /> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>

至于JsonIdentityInfo,下面是代码。 注意使用JsonIgnoreProperties(我主要用于所有集合,因为它创建了一个递归的大树,我想避免这种情况)

@Entity @Table(name = "o2_branch", catalog = "o2plus" ) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "id") @JsonIgnoreProperties(value = {"active", "modifiedBy", "modifiedTimestamp", "members", "staff"}) public class Branch implements java.io.Serializable { private Long id; private Address address; private String name; private String contactNumber; private Integer capacity; private String manager; private boolean active; private String modifiedBy; private Date modifiedTimestamp; private Set<Member> members = new HashSet<Member>(0); private Set<Staff> staff = new HashSet<Staff>(0);

希望它能帮助更多人。

Thanks people.

I was able to resolve this issue by using JsonIdentityInfo on my classes (both parent and child) along with a plugin called jackson-datatype-hibernate through which I enabled a feature called FORCE_LAZY_LOADING

If it helps anyone, below is the code for both the above configurations:

Create a class as below to enable jackson-datatype-hibernate

public class HibernateAwareObjectMapper extends ObjectMapper { public HibernateAwareObjectMapper() { Hibernate4Module hbm = new Hibernate4Module(); hbm.enable(Hibernate4Module.Feature.FORCE_LAZY_LOADING); registerModule(hbm); } }

Tell Spring to use the above ObjectMapper than the default provided by Jackson:

<mvc:annotation-driven> <mvc:message-converters> <!-- Use the HibernateAware mapper instead of the default --> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="com.adwitiya.o2plus.utilities.HibernateAwareObjectMapper" /> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>

As for the JsonIdentityInfo, below is the code. Notice the use of JsonIgnoreProperties (I've used this mainly for all the sets as it creates a recursive big tree and I wanted to avoid that)

@Entity @Table(name = "o2_branch", catalog = "o2plus" ) @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "id") @JsonIgnoreProperties(value = {"active", "modifiedBy", "modifiedTimestamp", "members", "staff"}) public class Branch implements java.io.Serializable { private Long id; private Address address; private String name; private String contactNumber; private Integer capacity; private String manager; private boolean active; private String modifiedBy; private Date modifiedTimestamp; private Set<Member> members = new HashSet<Member>(0); private Set<Staff> staff = new HashSet<Staff>(0);

Hope it helps more people.

更多推荐

本文发布于:2023-07-31 12:50:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1343806.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:亲子   序列化   Jackson   Handling   Parent

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!