JAXB-Eclipselink:XmlRootElement 和继承

发布于 2024-12-26 11:03:07 字数 2499 浏览 1 评论 0原文

使用 Eclipselink/MOXy 2.3 我在编组到 XML 时有以下用例:

abstract class MyAbstract {
}

class MyImpl extends MyAbstract {
}

class A {

    private MyAbstract myAbstract;

    // MyImpl is behind this
    public MyAbstract getMyAbstract() {
        return myAbstract;
    }

}

我在 oxm.xml 中定义了以下映射:

<java-type name="foo.MyAbstract" xml-accessor-type="NONE">
    <xml-see-also>
        foo.MyImpl
    </xml-see-also>
</java-type>

<java-type name="foo.MyImpl">
    <xml-root-element name="MyImpl" />
</java-type>

<java-type name="bar.A" xml-accessor-type="NONE">
    <xml-root-element name="A" />
    <java-attributes>
        <xml-element java-attribute="myAbstract" type="foo.MyAbstract" />
    </java-attributes>
</java-type>

现在这导致:

<A>
    <myAbstract xsi:type="myImpl">
        <!-- Mapped members of MyImpl + MyAbstract -->
    </myAbstract>
</A>

因为我不希望导出的 xml 中的属性名称我更改:

<java-type name="bar.A" xml-accessor-type="NONE">
    <xml-root-element name="A" />
    <java-attributes>
        <xml-element java-attribute="myAbstract" type="foo.MyAbstract" xml-path="."/>
    </java-attributes>
</java-type>

这导致:

<A>
    <!-- Members of MyImpl + MyAbstract marshalled without any wrapping element-->
</A>

我想要的是:

 <A>
    <MyImpl>
        <!-- Members of MyImpl + MyAbstract -->
    </MyImpl>
 </A>

问题是:我如何实现这一目标? MOXy 只是忽略 MyImpl 上的 XmlRootElement...

编辑:

尝试 Blaise 的建议给了我以下异常:

Exception [EclipseLink-60] (Eclipse Persistence Services - 2.3.2.v20111125-r10461):   
org.eclipse.persistence.exceptions.DescriptorException
The method [] or [getMyAbstract] is not defined in the object [bar.A].

现在这需要我之前遗漏的进一步信息,因为我认为它不相关:

A 类是一个接口,它定义:public X getMyAbstract(); MyAbstract 实现了 X(这就是我在接口 A 的映射中添加类型属性的原因)。

因此,使用 xml-element-ref MOXy 不再“看到” getter,而使用 xml-element 却可以。

Using Eclipselink/MOXy 2.3 i have following usecase in marshalling to XML:

abstract class MyAbstract {
}

class MyImpl extends MyAbstract {
}

class A {

    private MyAbstract myAbstract;

    // MyImpl is behind this
    public MyAbstract getMyAbstract() {
        return myAbstract;
    }

}

I have following mapping defined in oxm.xml:

<java-type name="foo.MyAbstract" xml-accessor-type="NONE">
    <xml-see-also>
        foo.MyImpl
    </xml-see-also>
</java-type>

<java-type name="foo.MyImpl">
    <xml-root-element name="MyImpl" />
</java-type>

<java-type name="bar.A" xml-accessor-type="NONE">
    <xml-root-element name="A" />
    <java-attributes>
        <xml-element java-attribute="myAbstract" type="foo.MyAbstract" />
    </java-attributes>
</java-type>

Now this results in:

<A>
    <myAbstract xsi:type="myImpl">
        <!-- Mapped members of MyImpl + MyAbstract -->
    </myAbstract>
</A>

Since i didnt want the property-name in the exported xml I changed:

<java-type name="bar.A" xml-accessor-type="NONE">
    <xml-root-element name="A" />
    <java-attributes>
        <xml-element java-attribute="myAbstract" type="foo.MyAbstract" xml-path="."/>
    </java-attributes>
</java-type>

which resulted in:

<A>
    <!-- Members of MyImpl + MyAbstract marshalled without any wrapping element-->
</A>

What i want is:

 <A>
    <MyImpl>
        <!-- Members of MyImpl + MyAbstract -->
    </MyImpl>
 </A>

The question is: how do i achieve this? MOXy is just ignoring my XmlRootElement on MyImpl...

EDIT:

Trying what Blaise suggested gives me following exception:

Exception [EclipseLink-60] (Eclipse Persistence Services - 2.3.2.v20111125-r10461):   
org.eclipse.persistence.exceptions.DescriptorException
The method [] or [getMyAbstract] is not defined in the object [bar.A].

Now this needs further information which i had left out before because i thought it was not relevant:

Class A is an interface which defines: public X getMyAbstract();
MyAbstract implements X (this is why i added the type-attribute in the mapping for interface A).

So, using xml-element-ref MOXy does not "see" the getter anymore, using xml-element it does.

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

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

发布评论

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

评论(1

捶死心动 2025-01-02 11:03:07

您要查找的映射是@XmlElementRef。这对应于 XML 模式中替换组的概念。

bar/oxm.xml

下面是 bar 包的外部映射文档。请注意 myAbstract 属性如何与 xml-element-ref 映射,它是 @XmlElementRef

<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="bar">
    <java-types>
        <java-type name="A" xml-accessor-type="NONE">
            <xml-root-element name="A" />
            <java-attributes>
                <xml-element-ref java-attribute="myAbstract"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

foo/oxm.xml

的 XML 表示形式,下面是foo 包的外部元数据文件:

<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="foo">
    <java-types>
        <java-type name="MyAbstract" xml-accessor-type="NONE">
            <xml-see-also>
                foo.MyImpl
            </xml-see-also>
        </java-type>
        <java-type name="MyImpl">
            <xml-root-element name="MyImpl" />
        </java-type>
    </java-types>
</xml-bindings>

演示

以下是此示例的演示代码:

package forum8853855;

import java.util.*;
import javax.xml.bind.*;    
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import bar.A;
import foo.MyImpl;

public class Demo {

    public static void main(String[] args) throws Exception {
        List<String> oxm = new ArrayList<String>(2);
        oxm.add("foo/oxm.xml");
        oxm.add("bar/oxm.xml");

        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, oxm);

        JAXBContext jc = JAXBContext.newInstance(new Class[] {A.class}, properties);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        A a = new A();
        a.setMyAbstract(new MyImpl());
        marshaller.marshal(a, System.out);
    }

}

输出

<?xml version="1.0" encoding="UTF-8"?>
<A>
   <MyImpl/>
</A>

了解更多信息

The mapping that you are looking for is @XmlElementRef. This corresponds to the concept of substitution groups in XML schema.

bar/oxm.xml

Below is the external mapping document for the bar package. Note how the myAbstract property is mapped with xml-element-ref which is the XML representation of @XmlElementRef

<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="bar">
    <java-types>
        <java-type name="A" xml-accessor-type="NONE">
            <xml-root-element name="A" />
            <java-attributes>
                <xml-element-ref java-attribute="myAbstract"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

foo/oxm.xml

Below is the external metadata file for the foo package:

<?xml version="1.0" encoding="UTF-8"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="foo">
    <java-types>
        <java-type name="MyAbstract" xml-accessor-type="NONE">
            <xml-see-also>
                foo.MyImpl
            </xml-see-also>
        </java-type>
        <java-type name="MyImpl">
            <xml-root-element name="MyImpl" />
        </java-type>
    </java-types>
</xml-bindings>

Demo

Below is demo code for this example:

package forum8853855;

import java.util.*;
import javax.xml.bind.*;    
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import bar.A;
import foo.MyImpl;

public class Demo {

    public static void main(String[] args) throws Exception {
        List<String> oxm = new ArrayList<String>(2);
        oxm.add("foo/oxm.xml");
        oxm.add("bar/oxm.xml");

        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, oxm);

        JAXBContext jc = JAXBContext.newInstance(new Class[] {A.class}, properties);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        A a = new A();
        a.setMyAbstract(new MyImpl());
        marshaller.marshal(a, System.out);
    }

}

Output

<?xml version="1.0" encoding="UTF-8"?>
<A>
   <MyImpl/>
</A>

For More Information

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