如何解决杰克逊无法处理JPA bean中的直接自引用问题

hyp*_*oad 5 java jax-rs jaxb jersey jackson

所以我正在使用Java,Hibernate,JPA注释,JAX-RS注释,JAXB注释,Jersey和Jackson JSON解析器开发RESTful数据API.

在尝试了Jersey提供的MAPPING和NATURAL JSON符号的各种配置后,我最终决定使用Jackson JSON解析器.除了这一个问题,杰克逊将是完美的......

我遇到的问题是Jackson没有使用JAXB注释"@XmlID"和"@XmlIDREF",我用它来表示我的实体关系,虽然"@JsonBackReference"和"@JsonManagedReference"帮助这个.在处理直接自引用属性时,这种组合似乎会崩溃.

这似乎是一个相当普遍的问题.你怎么能和杰克逊一起绕过这个限制?

以我的POJO为......

@XmlRootElement
public class Employee implements Serializable {
    private Date lastUpdatedOn;
    private Employee lastUpdatedBy;
    private Integer empId;

    @JoinColumn(nullable=false)
    @OneToOne
    @XmlIDREF
    public Employee getLastUpdatedBy() {
        return createdBy;
    }
    public void setLastUpdatedBy(Employee lastUpdatedBy) {
        this.lastUpdatedBy = lastUpdatedBy;
    }

    @Temporal(TemporalType.TIMESTAMP)
    public Date getLastUpdatedOn() {
        return createdOn;
    }
    public void setLastUpdatedOn(Date lastUpdatedOn) {
        this.lastUpdatedOn = lastUpdatedOn;
    }
    @XmlID
    @XmlJavaTypeAdapter(IntegerAdapter.class)
    public Integer getEmpId() {
        return empId;
    }
    public void setEmpId(Integer empId) {
        this.empId = empId;
    }
}
Run Code Online (Sandbox Code Playgroud)

......以及以下EmployeeResource ......

@Path("/Employees")
public class EmployeeResource {
  private List<Employee> employees;

  public List<Employee> getEmployees() {
    return employees;
  }
  public void setEmployees(List<Employee> employees) {
    this.employees = employees;
  }

  @GET
  @Path("/{empId}")
  public Response getEmployees(
    @Context UriInfo ui
    , @PathParam("id") Integer empId
  ) {
    this.employees = HibernateUtil.pagedQuery(
      Employee.class
      , new ArrayList() {
        Restrictions.eq("empId",empId)
      }
    );
    return Response.ok(this).build();
  }
}
Run Code Online (Sandbox Code Playgroud)

我的JAX-RS资源将产生以下错误

org.codehaus.jackson.map.JsonMappingException: Direct self-reference leading to cycle (through reference chain: resources.EmployeeResource["employees"]->java.util.ArrayList[0]->entities.Employee["lastUpdatedBy"])
Run Code Online (Sandbox Code Playgroud)

......但我希望它能产生......

{
  "employees" : [ {
    "lastUpdatedOn" : 1331149770737,
    "lastUpdatedBy" : 10150,
    "empId" : 10150,
  } ],
}
Run Code Online (Sandbox Code Playgroud)

大家提前感谢!

笔记:

  1. 我使用IntegerAdapter.class将其转换为字符串,以便它可以使用@XmlID注释.
  2. 上面描述的Employee和EmployeeResource类只是我实际实现的缩写版本,但它们代表了我的实现中与此直接自引用问题相关的部分.

编辑#1 2012.03.10对不起,在这个问题的第一个版本中,我使用泽西岛的自然符号与我与杰克逊运行的版本之间的版本感到困惑.我已经修改了我的问题,以更准确地反映我与杰克逊的直接自我引用问题.

Sta*_*Man 4

Jackson 1.x 没有对解决循环引用的具体支持,但支持处理父/子样式依赖关系:博客条目有更多信息。

Jackson 2.0 将使用新的注释支持任意对象 ID/引用处理@JsonIdentityInfo,因此也许可以用来解决问题。官方 2.0 版本尚未发布,但候选版本(最新的是 RC2)已经发布,以防您想查看。不确定它是否能解决您的问题,但也许会有所帮助。

编辑:实际上,Jackson JAXB 注释模块将支持@XmlID/ @XmlIDREF2.0.0 - 这刚刚实现,请参见此处