Json和Java - 循环参考

Faa*_*ass 17 java json circular-reference jackson

我有并且发布了循环参考.

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

java.lang.IllegalStateException: 
    Cannot call sendError() after the response has been committed
Run Code Online (Sandbox Code Playgroud)

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

控制器方法标题是:

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

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

Viv*_*ath 35

有两种方法可以解决这个问题.如果必须将实体暴露给外界,我建议添加@JsonIgnore导致循环引用的属性.这将告诉杰克逊不要序列化该属性.

另一种方法是使用Jackson提供的双向功能.你可以使用@JsonManagedReference@JsonBackReference.@JsonManagedReference是属性的"前进"部分,它将正常序列化.@JsonBackReference是参考的"后面"部分; 它不会被序列化,但是当"反向"类型被反序列化时将被重建.

你可以在这里看看这些例子.

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

UPDATE

这是一个很好的博客文章在这里是进入你能处理杰克逊双向关系的各种方式的细节.它描述了使用的解决方案@JsonIgnore,@JsonManagedReference并且@JsonBackReference,@JsonIdentityInfo,@JsonView和自定义序列为好.这是对您可以使用的各种技术的全面综述.


pav*_*van 8

单个注释@JsonIdentityInfo可以解决问题.它也处理循环引用.参考

  • 唯一的问题是当您的身份字段为空时。那么你又回到了第 1 方格 - 循环引用。 (3认同)
  • 这个答案并不表明这个注解是在父类中还是在子类中。通过指出这些信息可以大大改善答案。 (3认同)