2012-11-21 10 views
6

RestFul-Webservice(Jersey)コンテキストでは、オブジェクトグラフをXMLとJSONにマーシャリング/シリアル化する必要があります。簡単にするために私は2-3のクラスに問題があることを説明しよう:ContainerではなくID参照でJAXBのシリアライズされたXML

Person.java

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Person { 

    private String name; 

    // @XmlIDREF 
    @XmlElement(name = "house") 
    @XmlElementWrapper(name = "houses") 
    private Collection<House> houses; 

    public Person() {} 

    public Person(String name, Collection<House> houses) { 
     this.name = name; 
     this.houses = houses; 
    } 
} 

House.java

@XmlAccessorType(XmlAccessType.FIELD) 
public class House { 

    // @XmlID 
    public String name; 

    public String location; 

    public House() {} 

    public House(String name, String location) { 
     this.name = name; 
     this.location = location; 
    } 
} 

今私は人をシリアル化するとき、 XMLは次のようになります。

<people> 
    <person> 
     <name>Edward</name> 
     <houses> 
      <house> 
       <name>MyAppartment</name> 
       <location>London</location> 
      </house> 
      <house> 
       <name>MySecondAppartment</name> 
       <location>London</location> 
      </house> 
     </houses> 
    </person> 

    <person> 
     <name>Thomas</name> 
     <houses> 
      <house> 
       <name>MyAppartment</name> 
       <location>London</location> 
      </house> 
      <house> 
       <name>MySecondAppartment</name> 
       <location>London</location> 
      </house> 
     </houses> 
    </person> 
</people> 

ここでの問題は、同じ家が複数回リストされていることです。最初のXMLがあまりにも冗長だったが、この1つは情報の不足

<people> 
    <person> 
     <name>Edward</name> 
     <houses> 
      <house>MyAppartment</house> 
      <house>MySecondAppartment</house> 
     </houses> 
    </person> 

    <person> 
     <name>Thomas</name> 
     <houses> 
      <house>MyAppartment</house> 
      <house>MySecondAppartment</house> 
     </houses> 
    </person> 
</people> 

:今、私はこれに似たXMLにつながるコメントを外しXmlIDREFXmlID注釈を追加します。どのようにして作成(およびアンマーシャリング)することができますのようなもの:私はオブジェクトグラフ内の各新しい要素のための余分なクラスを記述したくないので

<people> 
    <person> 
     <name>Edward</name> 
     <houses> 
      <house>MyAppartment</house> 
      <house>MySecondAppartment</house> 
     </houses> 
    </person> 

    <person> 
     <name>Thomas</name> 
     <houses> 
      <house>MyAppartment</house> 
      <house>MySecondAppartment</house> 
     </houses> 
    </person> 

    <houses> 
     <house> 
      <name>MyAppartment</name> 
      <location>London</location> 
     </house> 
     <house> 
      <name>MySecondAppartment</name> 
      <location>London</location> 
     </house> 
    </houses> 
</people> 

は、ソリューションは、ジェネリックにする必要があります。事前に

@Path("rest/persons") 
public class TestService { 
    @GET 
    @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_JSON }) 
    public Collection<Person> test() throws Exception { 
     Collection<Person> persons = new ArrayList<Person>(); 
     Collection<House> houses = new HashSet<House>(); 
     houses.add(new House("MyAppartment", "London")); 
     houses.add(new House("MySecondAppartment", "London")); 
     persons.add(new Person("Thomas", houses)); 
     persons.add(new Person("Edward", houses)); 
     return persons; 
    } 
} 

ありがとう:

は完全を期すために、ここで安らかなWebサービスです。

+1

[JAXBが最初に封じ込めで整列化した後、後で参照するために@XmlIDREFで整列化できますか?](http://stackoverflow.com/questions/7587095/can-jaxb-marshal-by-containment-at-first -then-marshal-by-xmlidref-for-subsequen) –

+0

すべての値を含むサブクラス「 '' House'''の浅いインスタンスを返す '' XmlAdapter'''を書くか、インスタンス、はい。しかし、多くの欠点があります:(1)オブジェクトグラフに各クラスのサブクラスを書く必要があります。(2) '' '@ XmlAttribute'''を' '' marshal( ) '' 'と' 'unmarshal()' 'メソッドを呼び出し、最後に(3)ルートノードの子としてハウスを含むXMLを生成しません。モデルを変更するときに私が採用しなければならないことはたくさんあります。そして、すべての情報がそこにあるので、すべてこれは自動的に行うことができます。 – steffen

答えて

2

最後に与えたXMLの例に一致する形式にシリアル化しようとしている場合、オブジェクトグラフが正しく構成されていないと思われます。

Personオブジェクトのコレクションを関連する家に提供し、Houseオブジェクトのコレクションを提供する場合は、両方のコレクションを含むシリアル化されたXMLメッセージを返す必要があります。あなたの説明に基づいてPerson-Houseの関連付けを行う正しい場所に@XmlIDREF@XmlIDという注釈があるように見えますが、両方のコレクションを返すのではなくPersonオブジェクトのコレクションのみを返します。

あなたのWebサービスは、(あなたがそれをシリアル化する方法について明確だ表示されているシリアル化を除外)より、次のようになります。

@Path("rest/persons") 
public class TestService { 
    @GET 
    @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_JSON }) 
    public Map<String, Object> test() throws Exception { 
     Map<String, Object> peopleAndHouses = new HashMap<String, Object>(); 
     Collection<Person> persons = new ArrayList<Person>(); 
     Collection<House> houses = new HashSet<House>(); 

     houses.add(new House("MyAppartment", "London")); 
     houses.add(new House("MySecondAppartment", "London")); 
     persons.add(new Person("Thomas", houses)); 
     persons.add(new Person("Edward", houses)); 

     peopleAndHouses.put("houses", houses); 
     peopleAndHouses.put("people", persons); 
     return peopleAndHouses; 
    } 
} 

これを達成する他の方法があります(たとえば、ラッパーオブジェクトを作成します人や家などのためのコレクション属性を持っていますが)うまくいけば、あなたはそのアイデアを得るでしょう。

関連する問題