可以将XStream配置为具有双向(父/子)引用吗?

时间:2011-01-14 19:54:40

标签: java xstream

我正在使用XStream加载如下结构的文件:

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

进入这样一个类:

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

public class Child { 
 private Parent parent; 
}

我希望能够这样做:parent.getChildren().get(0).getParent()

我希望能够使用XML。我知道我可以在子项下添加对父项的引用,但这似乎非常多余。由于XML结构,我知道childs parent。

XStream是否支持此功能?

3 个答案:

答案 0 :(得分:3)

是Xstream支持反向链接以避免循环引用。它默认情况下会这样做,但是它是否可以证明需要它的消息是否真的合适。它可以通过网络释放一些数据,但实际上不是一个“消息”,更像是一个序列化的对象。

您的子对象需要有一个指向父对象的指针。

答案 1 :(得分:2)

一种选择是在父级中使用readResolve来设置反向引用。根据此处的XStream FAQ,将以与标准库序列化相同的方式调用此方法:http://x-stream.github.io/faq.html#Serialization_initialize_transient

调用readResolve时,Parent及其所有子项已经被反序列化,因此您可以在此时设置反向引用。

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

答案 2 :(得分:0)

如果您愿意考虑使用XStream之外的其他内容,那么EclipseLink JAXB (MOXy)可以使用@XmlInverseReference轻松处理双向属性(我是MOXy技术主管)。

您的对象模型将映射为:

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());
        }
    }

}

要将MOXy指定为JAXB实现,您需要在与模型类相同的包中包含一个名为jaxb.properties的文件,并带有以下条目:

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

下面是我对JAXB和XStream的比较的链接: