2011-01-14 3 views
3

私はこのような構造のファイルをロードするためにXStreamのを使用しています:私はこれを行うことができるようにしたいと思いXStreamは双方向(親/子)参照を持つように設定できますか?

public class Parent(){ 
private List<Child> children; 
} 

public class Child { 
private Parent parent; 
} 

parent.getChildren().get(0).getParent()

このようなクラスに

<parent> 
    <child/> 
    <child/> 
</parent> 

を私はそれが座っているようにXMLを使用できるようにしたいと思います。私は子供の下の親に参照を追加することができますが、それは非常に冗長なようです。 XML構造のため、子の親を知っています。

XStreamはこれをサポートしていますか?

答えて

3

はいXstreamは、循環参照を避けるためにバックリンクをサポートしています。これはデフォルトでは行いますが、これを必要とするメッセージが本当に適切なものかどうかは議論の余地があります。そのネットワーク上のデータをちょうどチャッキングしても問題ありませんが、実際には「メッセージ」ではなく、よりシリアライズされたオブジェクトです。

あなたの子オブジェクトは親に対して "ポインタ"を持つ必要があります。

+0

これは良い考えではないかもしれないというあなたの意見に同意しますが、私はいくつかの外部の制約の下で動作しています。したがって、 'public class Child {プライベート親の親; } '。 XStreamはこれを自動的に入力しますか?これを処理するために設定する必要があるXStreamの注釈や設定は何ですか? – Freiheit

+0

well - オブジェクトをマーシャリングするときに参照が設定されている場合、オブジェクトを非整列化するときにそのオブジェクトが設定されます。IIRCそれはちょうど起こる。それを試しましたか?それは私が正常に動作するかどうかを確認する方法です! – time4tea

+0

それは時間がかかりません:System.out.println(new XStream()。toXML(parent)); – time4tea

0

XStream以外のものを使用することを検討したい場合は、EclipseLink JAXB (MOXy)@XmlInverseReference(私はMOXy techリードです)で双方向プロパティを簡単に処理します。

あなたのオブジェクトモデルのようにマップされます:

import java.util.List; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Parent { 

    private List<Child> children; 

    @XmlElement(name="child") 
    public List<Child> getChildren() { 
     return children; 
    } 

    public void setChildren(List<Child> children) { 
     this.children = children; 
    } 

} 

と(親プロパティに@XmlInverseReferenceの使用を注意してください):

import org.eclipse.persistence.oxm.annotations.XmlInverseReference; 

public class Child { 

    private Parent parent; 

    @XmlInverseReference(mappedBy="children") 
    public Parent getParent() { 
     return parent; 
    } 

    public void setParent(Parent parent) { 
     this.parent = parent; 
    } 

} 

デモコードは(input.xmlにようになります。あなたの質問からXMLを参照してください):

import java.io.File; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Unmarshaller; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Parent.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Parent parent = (Parent) unmarshaller.unmarshal(new File("input.xml")); 

     for(Child child : parent.getChildren()) { 
      System.out.println(child.getParent()); 
     } 
    } 

} 

JAXB実装としてMOXyを指定するには次のエントリを使用してモデルクラスと同じパッケージでjaxb.propertiesと呼ばれるファイルが含ま:以下

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

はJAXBやXStreamのの私の比較へのリンクです:

+1

あなたの答えはおそらくより良い道ですが、このプロジェクトはXStreamにロックされています。 – Freiheit

2

1つのオプションは、逆参照を設定するために親にreadResolveを使用することです。これは、ここにXStreamのFAQによると、標準ライブラリのシリアル化と同じ方法で呼び出されます:readResolveは、呼び出されParentとそのすべての子供たちは、すでに直列化復元されていますので、あなたはその時点で後方参照を設定することができますされてhttp://x-stream.github.io/faq.html#Serialization_initialize_transient

public class Parent { 
    private List<Child> children = new ArrayList<Child>(); 
    private Object readResolve() { 
    for(Child child: children) { 
     child.setParent(this); 
    } 
    return this; 
    } 
} 
関連する問題