java - 为什么 Jackson 的 PropertyGenerator 会阻止递归循环

标签 java json rest jackson jax-rs

我有两个双向映射的实体。具有注册集合和注册本身的车辆。这些实体作为 REST 服务公开。

@Entity
@XmlRootElement
public class Vehicle implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String brand;
  private String type;

  @OneToMany(mappedBy = "vehicle", fetch = FetchType.EAGER)
  private List<Registration> registrations;
}

问题是 FetchType.EAGER 产生了一个无限递归

@Entity
@XmlRootElement
public class Registration implements Serializable {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  private String name;

  @ManyToOne
  private Vehicle vehicle;
}

经过一番研究,我发现我必须将注释 @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") 添加到 Vehicle 类才能解决问题。

我的问题是:PropertyGenerator 类实际上做了什么?

最佳答案

问题不是因为 FetchType.EAGERFetchType.EAGER 是一个 JPA 注释,在您使用 Jackson 序列化 Vehicle 实例时不会发挥作用。

实际发生的是 Jackson 正在序列化一个车辆,这会触发注册列表的序列化,这会序列化一个具有注册列表的车辆,等等。

如您所见,@JsonIdentityInfo 注释使无限递归短路,但这并不是因为您指定了特定的 PropertyGenerator@JsonIdentityInfo 的 JavaDoc 提供了一些关于正在发生的事情的见解:

@JsonIdentityInfo Annotation used for indicating that values of annotated type or property should be serializing so that instances either contain additional object identifier (in addition actual object properties), or as a reference that consists of an object id that refers to a full serialization. In practice this is done by serializing the first instance as full object and object identity, and other references to the object as reference values.

换句话说,第一次序列化某些内容时,您将获得完整的序列化 JSON/XML 版本。下次序列化该对象时,您将获得对第一个序列化对象的引用。

还有其他方法可以解决这个问题。查看Infinite Recursion with Jackson JSON and Hibernate JPA issue (你的问题可以说是这个问题的重复)。那里的答案建议您也可以使用 @JsonIgnore@JsonManagedReference@JsonBackReference 的组合来避免无限递归。

现在,针对您关于 PropertyGenerator 实际作用的具体问题:它指示 Jackson 使用您类中的特定属性作为对象的完整序列化版本的引用。您将“id”指定为属性,因此在生成的序列化 JSON/XML 中您应该看到,如果您有一个 ID 为 342 的对象,那么第一个序列化对象将显示 id 和所有其他序列化属性,但随后每次该对象都是序列化后,您只会看到序列化为对原始对象的引用的 342。

关于java - 为什么 Jackson 的 PropertyGenerator 会阻止递归循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33342827/

相关文章:

java - Map.clear() 与新 map : Which one will be better?

php - 如果值设置为 0,如何排除数据?

json - 使用 json 数据将 curl post 形成为 swift http post

java - 如何对 Jersey 的用户进行身份验证

json - 从 Bitbucket 中检索文本文件内容

java - 照片未正确上传 GCS App Engine

java - 如何在 libgdx 的中心获得舞台?

java - 如何决定一个对象是否应该成为聚合的一部分

java - 在没有 XML 的情况下以编程方式运行 testng 会抛出 NoSuchMethodError XmlPackage

json - 我需要获得 jsonpath 匹配才能使用 Spring mock mvc 的依赖是什么?