概述
提出问题
在基于Jackson类库将对象转化为json字符串时,如果对象中存在互相依赖,则会产生无限循环的情况,具体情况如下:
BuyerEntity.java
@Table(name="t_buyer")
@Entity
@ToString(callSuper=true)
@Data
@EqualsAndHashCode(callSuper=false)
public class BuyerEntity extends BaseEntity {
@Column(nullable=false)
private String name;
@Column
private Integer age;
@Column(name="sex")
private Integer sex;
//@Enumerated(EnumType.ORDINAL)
@Column(nullable=false, name="gender")
@Convert(converter = GenderConverter.class)
private Gender gender = Gender.Male;
@Column
private String email;
@OneToMany(cascade= {CascadeType.ALL}, mappedBy="buyer")
private List<OrderEntity> orders;
}
OrderEntity.java
@Entity
@Table(name="t_order")
@ToString(callSuper=true)
@Data
public class OrderEntity extends BaseEntity {
//商品消费数据量
@Column
private int count;
//消费记录的总价
@Column(name="total_fee")
private double totalFee;
//折扣率
@Column(name="discount_rate")
private double discountRate;
@ManyToOne(cascade= {CascadeType.REFRESH})
@JoinColumn(name="buyer_id", referencedColumnName="id")
private BuyerEntity buyer;
}
生成Json字符串的过程如下:
BuyerEntity buyer = new BuyerEntity();
buyer.setAge(12);
buyer.setCreatedTime(new Date());
buyer.setUpdatedTime(new Date());
buyer.setEmail("123@123.cn");
buyer.setGender(Gender.Female);
buyer.setName("zhangsan");
OrderEntity order1 = new OrderEntity();
order1.setCount(12);
order1.setCreatedTime(new Date());
order1.setUpdatedTime(new Date());
order1.setTotalFee(123.3);
order1.setDiscountRate(0.80);
order1.setBuyer(buyer);
OrderEntity order2 = new OrderEntity();
order2.setCount(9);
order2.setCreatedTime(new Date());
order2.setUpdatedTime(new Date());
order2.setTotalFee(35.3);
order2.setDiscountRate(0.60);
order1.setBuyer(buyer);
List<OrderEntity> orders = Lists.newArrayList();
orders.add(order1);
orders.add(order2);
buyer.setOrders(orders);
ObjectMapper objectMapper = new ObjectMapper();
String jsonStr = objectMapper.writeValueAsString(buyer);
System.out.println(jsonStr);
上述结果信息中则会出现如下的无限循环:
{"code":0,"message":"success","data":{"id":2,"createdTime":"2019-03-19T01:30:53.123+0000","updatedTime":"2019-03-19T01:30:53.123+0000","version":0,"name":"zhangsan","age":12,"sex":null,"gender":"Female","email":"123@123.cn","orders":[{"id":3,"createdTime":"2019-03-19T01:30:53.123+0000","updatedTime":"2019-03-19T01:30:53.123+0000","version":0,"count":12,"totalFee":123.3,"discountRate":0.8,"buyer":{"id":2,"createdTime":"2019-03-19T01:30:53.123+0000","updatedTime":"2019-03-19T01:30:53.123+0000","version":0,"name":"zhangsan","age":12,"sex":null,"gender":"Female","email":"123@123.cn","orders":[{"id":3,"createdTime":"2019-03-19T01:30:53.123+0000","updatedTime":"2019-03-19T01:30:53.123+0000","version":0,"count":12,"totalFee":123.3,"discountRate":0.8,"buyer":{"id":2,"createdTime":"2019-03-19T01:30:53.123+0000","updatedTime":"2019-03-19T01:30:53.123+0000","version":0,"name":"zhangsan","age":12,"sex":null,"gender":"Female","email":"123@123.cn","orders":[{"id":3,"createdTime":"2019-03-19T01:30:53.123+0000","updatedTime":"2019-03-19T01:30:53.123+0000","version":0,"count":12,"totalFee":123.3,"discountRate":0.8,"buyer":{"id":2,"createdTime":"2019-03-19T01:30:53.123+0000","updatedTime":"2019-03-19T01:30:53.123+0000","version":0,"name":"zhangsan","age":12,"sex":null,"gender":"Female","email":"123@123.cn","orders":[{"id":3,"createdTime":"2019-03-19T01:30:53.123+0000","updatedTime":"2019-03-19T01:30:53.123+0000","version":0,"count":12,"totalFee":123.3,"discountRate":0.8,"buyer":{"id":2,"createdTime":"2019-03-19T01:30:53.123+0000","updatedTime":"2019-03-19T01:30:53.123+0000","version":0,"name":"zhangsan","age":12,"sex":null,"gender":"Female","email":"123@123.cn","orders":[{"id":3,"createdTime":"2019-03-19T01:30:53.123+0000","updatedTime":"2019-03-19T01:30:53.123+0000","version":0,"count":12,"totalFee":123.3,"discountRate":0.8,"
问题解决
那该问题该如何破解呢?
- 使用 @JsonManagedReference @JsonBackReference
@JsonManagedReference: 正常输出Json的字符串
@JsonBackReference: 则会忽略输出json的字符串 - @JsonIgnore: 其本身是忽略json的字符串输出的。
解决方案
于是将@JsonManagedReference 放到BuyerEntity.java中的List之上。
@JsonBackReference
@ManyToOne(cascade= {CascadeType.REFRESH})
@JoinColumn(name="buyer_id", referencedColumnName="id")
private BuyerEntity buyer;
与之相对应的是另外一个:
@JsonManagedReference
@OneToMany(cascade= {CascadeType.ALL}, mappedBy="buyer")
private List<OrderEntity> orders;
测试用例
public class JacksonCircularReferenceTest {
private ObjectMapper objectMapper = new ObjectMapper();
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void test() throws JsonProcessingException {
BuyerEntity buyer = new BuyerEntity();
buyer.setAge(12);
buyer.setCreatedTime(new Date());
buyer.setUpdatedTime(new Date());
buyer.setEmail("123@123.cn");
buyer.setGender(Gender.Female);
buyer.setName("zhangsan");
OrderEntity order1 = new OrderEntity();
order1.setCount(12);
order1.setCreatedTime(new Date());
order1.setUpdatedTime(new Date());
order1.setTotalFee(123.3);
order1.setDiscountRate(0.80);
order1.setBuyer(buyer);
OrderEntity order2 = new OrderEntity();
order2.setCount(9);
order2.setCreatedTime(new Date());
order2.setUpdatedTime(new Date());
order2.setTotalFee(35.3);
order2.setDiscountRate(0.60);
order1.setBuyer(buyer);
List<OrderEntity> orders = Lists.newArrayList();
orders.add(order1);
orders.add(order2);
buyer.setOrders(orders);
String jsonStr = objectMapper.writeValueAsString(buyer);
System.out.println(jsonStr);
}
}
参考资料
- https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion
最后
以上就是英勇皮卡丘为你收集整理的Jackson JSON包在从对象映射到Json字符串过程的循环依赖问题-分析与解决的全部内容,希望文章能够帮你解决Jackson JSON包在从对象映射到Json字符串过程的循环依赖问题-分析与解决所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复