【问题标题】:How to get around Jackson's inability to handle direct self-references in JPA beans如何解决 Jackson 无法处理 JPA bean 中的直接自引用的问题
【发布时间】:2012-03-09 22:49:05
【问题描述】:

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

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

我遇到的问题是 Jackson 不能使用 JAXB 注释“@XmlID”和“@XmlIDREF”,我用它们来表示我的实体关系,尽管“@JsonBackReference”和“@JsonManagedReference “帮助解决这个问题。在处理直接的自引用属性时,这种组合似乎失效了。

这似乎是一个相当普遍的问题。你们中的任何人是如何绕过 Jackson 的这一限制的?

以我的 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;
    }
}

...以及以下 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();
  }
}

我的 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"])

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

{
  "employees" : [ {
    "lastUpdatedOn" : 1331149770737,
    "lastUpdatedBy" : 10150,
    "empId" : 10150,
  } ],
}

提前谢谢大家!

注意事项:

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

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

【问题讨论】:

  • 我认为您的问题与 @XmlID 原样无关,而是与 JSON 基础知识有关。 JSON 不支持类型,因此"10150"(字符串)和10150(整数,但不支持)是“相同的”。
  • 我不得不不同意。 JSON 对 Object、Array、String 和 number 等类型有了解,www.json.org 。
  • 我错了对不起。我相信你需要的是从Dateint 的转换器。参见示例here
  • 对不起@dma_k,我在写这个问题时感到困惑。我试图回去更具体。最初我只是使用 Jersey 的自然注释,它不能很好地处理日期。现在我正在使用 Jackson,所有字符串、日期(时间戳)和数字都已正确序列化。但是,我现在遇到了这个直接的自引用问题,当 Jersey 使用 JAXB 注释“@XmlID”和“@XmlIDREF”时,这不是问题。

标签: java jaxb jersey jax-rs jackson


【解决方案1】:

Jackson 1.x 不支持解析循环引用,但支持处理父/子样式依赖:this 博客条目有更多信息。

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

编辑:实际上,Jackson JAXB 注释模块将支持 2.0.0 的 @XmlID / @XmlIDREF - 这刚刚实现,请参阅 here

【讨论】:

猜你喜欢
  • 2021-12-19
  • 1970-01-01
  • 2011-06-21
  • 2021-11-03
  • 1970-01-01
  • 2015-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多