2009-10-07 74 views
4

我們在過去幾個月使用Jersey(Java REST庫)進行項目,並熱愛它。但本週JAXB遇到了一個問題。JAXB和多個對象關係

我有是有2個孩子,他們每個人都有 孩子,其中一些孩子的相互引用的元素。

讓我來展示一些代碼。

Root root = new Root(); 

Parent parent1 = new Parent(); 
Parent parent2 = new Parent(); 

root.add(parent1); 
root.add(parent2); 

Child child1 = new Child(); 
Child child2 = new Child(); 
Child child3 = new Child(); 

parent1.add(child1); 
parent1.add(child2); 

parent2.add(child2); 
parent2.add(child3); 

所以我們有1個根,2個父母和3個孩子。

如果我把它發送到JAXB路徑上,我似乎找回了4個孩子。
每個家長都有自己的child2副本。

反正是有得到JAXB以連載的關係,並表明,無論是parent1和parent2指向同一個對象?

我們最近才發現這個問題,當時正在傳輸更復雜的元素。

如果沒有辦法讓JAXB做到這一點(這是我認爲此刻),有沒有人有任何建議,我可以在澤西做一些魔術來重新建立關係?

回答

3

這對JAXB來說不是問題,因爲它是模型的問題。如果XML沒有提供標準的機制來表達這一點,您希望JAXB如何呈現XML中的關係? XML的消費者和生產者都需要有一個商業邏輯層,它可以同意代表性。

我建議你需要重新編碼你的數據。例如,而不是具有爲包含在裏面父母孩子,你可以扁平化的東西出來:

<parent id="parent1"> 
    <child ref="child1"/> 
    <child ref="child2"/> 
</parent> 

<parent id="parent2"> 
    <child ref="child2"/> 
    <child ref="child3"/> 
</parent> 

<child id="child1"/> 
<child id="child2"/> 
<child id="child3"/> 

無論機制讀取和寫入這種結構必須知道這一切意味着什麼,但我沒有看到任何其他好方法來做到這一點。

另一個令人感興趣的問題是XStream在對對象圖進行序列化/反序列化時確實有support for object references,但它是完全專有的機制。

0

只是快速的想法:做Child對象實現適當的equals()方法?

1

你可能寫一個適配器類的根類,它的解組可以清理子對象,以便移除重複做。

0

正如其他答案中所述。這是JAXB的設計。

你可以做的是手工塗膠您認爲是串行化之前相同的對象是什麼多個副本。那麼你不需要爲對象使用自己獨特的ID,這樣就可以從其他對象中區分出克隆。

8

JAXB不支持在使​​用樹@ XmlID/@ XmlIDREF的組合物之間的非安全殼的引用。對此的要求是樹中的所有對象也必須被包含關係引用。在你的模型中,這可能涉及給Root一個Child集合。

下面將是你的代碼的修改版本:

Root root = new Root(); 

Parent parent1 = new Parent(); 
Parent parent2 = new Parent(); 

root.add(parent1); 
root.add(parent2); 

Child child1 = new Child(); 
child1.id = "1"; 
root.add(child1); 
parent1.add(child1); 

Child child2 = new Child(); 
child2.id = "2"; 
root.add(child2); 
parent1.add(child2); 
parent2.add(child2); 

Child child3 = new Child(); 
child3.id = "3"; 
root.add(child3); 
parent2.add(child3); 

那麼你的模型類會是什麼樣子:

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Root { 

    public List<Parent> parent = new ArrayList<Parent>(); 
    public List<Child> child = new ArrayList<Child>(); 

    public void add(Parent parent1) { 
     parent.add(parent1); 
    } 

    public void add(Child child1) { 
     child.add(child1); 
    } 
} 

import javax.xml.bind.annotation.XmlIDREF; 

public class Parent { 

    @XmlIDREF 
    public List<Child> child = new ArrayList<Child>(); 

    public void add(Child child1) { 
     child.add(child1); 
    } 

} 

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlID; 

public class Child { 

    @XmlID 
    @XmlAttribute 
    public String id; 

} 

生成的XML將如下所示:

<root> 
    <parent> 
     <child>1</child> 
     <child>2</child> 
    </parent> 
    <parent> 
     <child>2</child> 
     <child>3</child> 
    </parent> 
    <child id="1"/> 
    <child id="2"/> 
    <child id="3"/> 
</root>