【问题标题】:Json and Java - Circular ReferenceJson 和 Java - 循环参考
【发布时间】:2013-06-27 22:40:49
【问题描述】:

我对循环参考有疑问。

我有将对象返回到前端的 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,我是这个新手,我认为 jackson 自动解决了这个问题。

【问题讨论】:

标签: java json jackson circular-reference


【解决方案1】:

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

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

您可以查看示例here

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

更新

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

【讨论】:

  • 是的,我读到过这个。但问题是我不想“触摸” Hibernate 生成的实体。因为数据库不断增长,所以任何时候我都会添加任何我需要再次修改所有实体的内容。据我了解,我必须修改这两个选项的实体,对吗?
  • 我使用@JsonManagedReference 和@JsonBackReference 可以吗?
【解决方案2】:

单个注解@JsonIdentityInfo 解决了这个问题。它也处理循环引用。Reference

【讨论】:

  • 唯一的问题是当您的身份字段为空时。然后你回到方块 1 - 循环引用。
  • 这个答案并不表明这个注释是放在父类还是子类中。指出这些信息可以大大改善答案。
【解决方案3】:

@JsonbTransient 解决了我处理循环引用的问题:

@JsonbTransient // javax.json.bind.annotation.JsonbTransient
@ManyToOne
@JoinColumn(name = "userId", referencedColumnName = "id", nullable = false)
public AContainedEntity getAContainedEntity() {
       return aContainedEntity;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多