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

发布于 2024-10-11 23:19:58 字数 442 浏览 7 评论 0原文

我正在使用 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 结构,我知道孩子的父母。

XStream 支持吗?

I'm using XStream to load a file structured like this:

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

Into a class like this:

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

public class Child { 
 private Parent parent; 
}

I would like to be able to do this: parent.getChildren().get(0).getParent()

I would like to be able to use the XML as it sits. I know I can add references to the parent under children, but that seems very redundant. I know the childs parent because of its XML structure.

Does XStream support this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

静谧 2024-10-18 23:19:58

是的,Xstream 支持反向链接以避免循环引用。它默认执行此操作,但需要此操作的消息是否确实合适是有争议的。只需要通过网络传输一些数据就可以了,但它并不是真正的“消息”,而是一个序列化的对象。

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

Yes Xstream supports back-links to avoid circular references. It does this by default, but its arguable whether a message that required this is really a suitable one. Its fine for just chucking some data over the network, but isn't really a "message", more a serialized object.

Your child objects will need to have a "pointer" to the parent.

故人如初 2024-10-18 23:19:58

一种选择是在父级中使用 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;
  }
}

One option is to use readResolve in the parent to set the backreferences. This will be called in the same way as standard library serialization according to the XStream FAQ here: http://x-stream.github.io/faq.html#Serialization_initialize_transient

When readResolve is called, the Parent and all its children will have been deserialized already, so you can set the backreference at that time.

public class Parent {
  private List<Child> children = new ArrayList<Child>();
  private Object readResolve() {
    for( Child child: children ) {
      child.setParent(this);
    }
    return this;
  }
}
甜是你 2024-10-18 23:19:58

如果您愿意考虑使用 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 进行比较的链接:

If you are willing to consider using something other than XStream, then EclipseLink JAXB (MOXy) handles bi-directional properties easily with @XmlInverseReference (I'm the MOXy tech lead).

Your object model would be mapped as:

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

}

and (note the use of @XmlInverseReference on the parent property):

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

}

The demo code would look like (input.xml refers to the XML from your question):

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

}

To specify MOXy as the JAXB implementation you need to include a file called jaxb.properties in the same package as your model classes with the following entry:

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

Below is a link to my comparison of JAXB and XStream:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文