Json 和 Java - 循环参考

2022-09-01 20:07:12

我有循环引用并有问题。

我有Rest Webservices,它将对象返回到前端,问题是当我尝试返回具有多个引用的对象时,因此结果我得到了无限的响应,从而生成

java.lang.IllegalStateException: 
    Cannot call sendError() after the response has been committed

这些对象是由Hibernate Code Generation自动生成的,我需要在后端有循环引用,我只需要在使用Jackson将信息发送到前端之前将其删除即可。

控制器方法标头为:

@RequestMapping(value="/list", method=RequestMethod.POST)
public @ResponseBody eventResponse list(@RequestBody String sessionID) {

我没有做任何明确的事情来转换为Json,我是这个新手,我认为杰克逊自动解决了这个问题。


答案 1

有两种方法可以做到这一点。如果必须向外部世界公开实体,我建议在导致循环引用的属性上添加@JsonIgnore。这将告诉 Jackson 不要序列化该属性。

另一种方法是使用 Jackson 提供的双向功能。您可以使用@JsonManagedReference@JsonBackReference。 是属性的“转发”部分,它将正常序列化。 是引用的“后退”部分;它不会被序列化,但会在反序列化“正向”类型时被重构。@JsonManagedReference@JsonBackReference

您可以在此处查看示例。

这解决了您的评论:我认为在这种情况下,您可能想要做的是使用对外部世界可见的DTO。我喜欢这种方法,因为我不想将我的实体暴露给外部。这意味着 Jackson 注释将位于 DTO 上,而不是 enity 上。您将需要某种将实体转换为 DTO 的映射器或转换器。现在,当您对实体进行更改时,除非您修改映射器/转换器,否则它们不会传播到 DTO。我认为这是可以的,因为当您对实体进行更改时,您可以决定是否要公开该更改。

更新

这里有一篇很好的博客文章,详细介绍了在杰克逊中处理双向关系的各种方法。它描述了使用 、 和 、 和 以及 自定义序列化程序的解决方案。这是对您可以使用的各种技术的非常全面的描述。@JsonIgnore@JsonManagedReference@JsonBackReference@JsonIdentityInfo@JsonView


答案 2

单个批注可以解决问题。它还处理循环引用。参考@JsonIdentityInfo