2012-03-09 19 views
5

Java、Hibernate、JPAアノテーション、JAX-RSアノテーション、JAXBアノテーション、Jersey、Jackson JSONパーサーを使用してRESTfulデータAPIを作成しています。 。ジャクソンがJPA Beanで直接自己参照を処理できないようにする方法

Jerseyが提供するMAPPINGおよびNATURAL JSON表記のさまざまな設定を試した後、最終的にJackson JSONパーサーを使用することにしました。この1つの問題を除いて、ジャクソンは完璧です...

私が遭遇した問題は、ジャクソンが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; 
    } 
} 

...と、次の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(); 
    } 
} 

次のエラー

org.codehaus.jackson.map.JsonMappingException: Direct self-reference leading to cycle (through reference chain: resources.EmployeeResource["employees"]->java.util.ArrayList[0]->entities.Employee["lastUpdatedBy"]) 
が生成されます私のJAX-RSリソース

...しかし、私はそれを生産したい...

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

ありがとうございます、皆さん!

NOTES:

  1. 私はそれが@XmlID注釈で動作するように文字列に変換しIntegerAdapter.classを使用しています。
  2. 上記のEmployeeクラスとEmployeeResourceクラスは、実際の実装の簡略化されたバージョンですが、この直接自己参照問題に関連する実装の部分を表しています。

EDIT#1 2012年3月10日 私は私が私がジャクソンで実行しているバージョン対ニュージャージー州の自然な表記を使用しているバージョンの間で混乱してしまっていた、この質問の私の最初のバージョンでは、ごめんなさい。私はジャクソンとの直接の自己参照の問題をより正確に反映するために、私の質問を改訂しました。

+0

あなたの質問は、そのまま@ @ XmlID'とは関係ないと思いますが、JSONの基本には関係します。 JSONは型をサポートしていないので、 '' 10150 "'(文字列)と '10150'(整数型ですがサポートされていません)は"同じ "です。 –

+2

私は同意しなければならないでしょう。 JSONはObject、Array、String、numberなどの型を理解しています(www.json.org)。 – hypno7oad

+0

私は間違って申し訳ありませんでした。あなたが必要とするもの私は、Dateからintまでのコンバーターを信じています。例[here](http://blog.seyfi.net/2010/03/how-to-control-date-formatting-when.html)を参照してください。 –

答えて

4

ジャクソン1.xは循環参照を解決するための特別なサポートはありませんが、親子スタイルの依存関係を処理するためのサポートがあります。thisブログエントリにはより多くの情報があります。

ジャクソン2.0は、新しい@JsonIdentityInfo注釈を使用して、任意のオブジェクトID /参照処理をサポートしているため、おそらく問題を解決するために使用できます。公式2.0リリースはまだリリースされていませんが、リリース候補(最新のRC2)は、あなたが見たいと思った場合に備えています。あなたの問題を処理するかどうかは分かりませんが、おそらくそれが役に立ちます。

EDIT:実は、ジャクソンJAXB注釈モジュールは、2.0.0のための@XmlID/@XmlIDREFをサポートしています - これはちょうどhereを参照して、実施されました。

+0

リンクをありがとう。私はRC2を見ていきます。ジャージーのようにJAXBアノテーションを使うことができないのは少し残念ですが、 – hypno7oad

+0

JAXBアノテーションはXMLに固有のビットなので、ジャクソンの場合は2次的なものです(サポートされていますが、ネイティブメカニズムを使用するために適合させる必要があります)。 FWIW、JAXBアノテーションを実装する可能性を追跡する[https://github.com/FasterXML/jackson-module-jaxb-annotations/issues/2]があります。 – StaxMan

+0

ありがとう@Staxman、私はgithubスレッド上の目。 – hypno7oad

関連する問題