eclipselink/Moxy:基于类型的继承和属性名重载 [英] eclipselink/Moxy : inheritance and attribute name oveloading based on type

查看:20
本文介绍了eclipselink/Moxy:基于类型的继承和属性名重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正面临一个编组/解组问题,涉及使用 MOXy 的 JAXB 实现和外部元数据绑定文件的继承和多态性.

我无法控制 XML 文件或模型类.

模型中有多个类继承其他 DTO 类.这是我正在使用的环境的示例.此示例仅用于某些语法目的,实际环境涉及嵌套继承、集合等:

这里是要继承的类

 类 A {私有字符串名称;公共字符串 getName(){返回名称;}公共无效集合名称(字符串值){名称=价值;}}

这是一个继承的类

 B 类扩展 A {私有字符串 attrFromB;公共字符串 getAttrFromB(){返回 attrFromB;}公共无效 setAttrFromB(字符串值){attrFromB = 值;}}

还有一个

 类 C 扩展 A {私有字符串 attrFromC;公共字符串 getAttrFromC(){返回 attrFromC;}公共无效 setAttrFromC(字符串值){attrFromC=值;}}

这是一个容器类

 类 MyContainerClass{私有的我的对象;公共一个 getMyObject(){返回我的对象​​;}公共无效 setMyObject(一个值){我的对象 = 价值;}}

这是在 MyContainer 包含 A 的情况下它应该生成的 XML

 <MyContainer><MyObject nameA="foo"/></我的容器>

包含 B 的 MyContainer

 <MyContainer><MyObject nameB="foo" attrFromB="bar"/></我的容器>

和包含C的MyContainer

 <MyContainer><MyObject nameC="foo" attrFromC="bar"/></我的容器>

所以你已经可以看到即将出现的问题...

这是我要编写的映射文件:

 <?xml version="1.0"?><xml绑定xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"包名=com.test.example"版本=2.1"><java-type name="A" xml-accessor-type="NONE"><xml-root-element name="MyObject"/><java 属性><xml-element java-attribute="name" xml-path="@nameA"/></java-属性></java 类型><java-type name="B" xml-accessor-type="NONE"><xml-root-element name="MyObject"/><xml-see-also>com.test.example.A</xml.see.also><java 属性><xml-element java-attribute="name" xml-path="@nameB"/><xml-element java-attribute="attrFromB" xml-path="@attrFromB"/></java-属性></java 类型><java-type name="C" xml-accessor-type="NONE"><xml-root-element name="MyObject"/><xml-see-also>com.test.example.A</xml.see.also><java 属性><xml-element java-attribute="name" xml-path="@nameC"/><xml-element java-attribute="attrFromC" xml-path="@attrFromC"/></java-属性></java 类型><java-type name="MyContainer" xml-accessor-type="NONE"><xml-root-element name="MyContainer"/><java 属性><xml-element java-attribute="myObject" type="com.test.example.A" xml-path="MyObject"/></java-属性></java 类型></xml绑定>

<小时>

第一个问题是,如果我像这样绑定类,我会得到以下异常:

 [异常 [EclipseLink-44] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DescriptorException异常描述:数据库行 [UnmarshalRecord()] 中缺少类指示符字段.

第一个问题:我知道这很正常,Jaxb 需要一些方法来确定 MyContaioner.myObject 属性的类型.问题是我无法访问传入的 XML 文件,因此我无法向它们添加 xsi:type 字段.有没有办法根据其中是否存在特定属性来确定一个类?不管它的价值.如果源 xml 包含 @attrFromC 属性,我知道对象应该是 C 类型.如果它包含 attrFromB,它就是 B.

<小时>

第二个问题是name"属性在B和C内部不存在,所以jaxb忽略了em.

 --忽略类 [com.test.example.B] 上的属性 [name],因为没有为其生成属性.--忽略类 [com.test.example.C] 上的属性 [name],因为没有为其生成属性.

第二个问题:另一个问题是我不知道 Jaxb 是否能够像 XML 文件中预期的那样覆盖 xml 属性名称(@nameA、@nameB 和 nameC 都指 A.name),有什么办法吗?

提前感谢您的宝贵时间.

解决方案

以下是您的问题的答案.问题 2 的答案,也是问题 1 的答案.


<块引用>

第一个问题:我知道这是正常的,Jaxb 需要一些方法确定 MyContainer.myObject 属性的类型.问题是我无法访问传入的 XML 文件,所以我无法添加xsi:type 字段给他们.有没有办法根据是否存在特定属性?不管它的价值.如果源 xml 包含 @attrFromC 属性,我知道该对象应该是C类型.如果它包含attrFromB,它就是B.

您可以在 EclipseLink JAXB (MOXy) 对于这个用例:

MyClassExtractor

ClassExtractor 是一些代码,您可以实现这些代码来帮助 MOXy 确定它应该实例化哪个类.您将获得一个 Record,您可以通过 XPath 请求当前元素的属性是否存在,以确定应该实例化哪个类.

包 com.test.example;导入 org.eclipse.persistence.descriptors.ClassExtractor;导入 org.eclipse.persistence.sessions.*;公共类 MyClassExtractor 扩展 ClassExtractor{@覆盖公共类<?>extractClassFromRow(记录记录,会话会话){if(null != record.get("@attrFromB")) {返回 B.class;} else if(null != record.get("@attrFromC")) {返回 C.class;} 别的 {返回 A.class;}}}

元数据 (oxm.xml)

您可以使用 @XmlClassExtractor 注释配置 ClassExtractor.您也可以通过外部元数据文件执行此操作.我已经修改了您问题中包含的内容:

<?xml version="1.0"?><xml绑定xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"包名=com.test.example"版本="2.3"><java 类型><java-type name="A" xml-accessor-type="NONE"><xml-class-extractor class="com.test.example.MyClassExtractor"/><xml-root-element name="MyObject"/><java 属性><xml-attribute java-attribute="name" name="nameA"/></java-属性></java 类型><java-type name="B" xml-accessor-type="NONE"><xml-root-element name="MyObject"/><java 属性><xml-attribute java-attribute="name" name="nameB"/><xml-attribute java-attribute="attrFromB"/></java-属性></java 类型><java-type name="C" xml-accessor-type="NONE"><xml-root-element name="MyObject"/><java 属性><xml-attribute java-attribute="name" name="nameC"/><xml-attribute java-attribute="attrFromC"/></java-属性></java 类型><java-type name="MyContainerClass" xml-accessor-type="NONE"><xml-root-element name="MyContainer"/><java 属性><xml-element java-attribute="myObject" name="MyObject"/></java-属性></java 类型></java-types></xml绑定>

演示

以下演示代码从您的问题中解组每个 XML 文档,并输出 myObject 属性所持有的类型:

包 com.test.example;导入 java.io.StringReader;导入 java.util.*;导入 javax.xml.bind.*;导入 org.eclipse.persistence.jaxb.JAXBContextFactory;公共类演示{公共静态 void main(String[] args) 抛出异常 {映射<字符串,对象>properties = new HashMap();properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "com/test/example/oxm.xml");JAXBContext jc = JAXBContext.newInstance(new Class[] {MyContainerClass.class}, properties);解组器 unmarshaller = jc.createUnmarshaller();StringReader aXml = new StringReader("<MyContainer><MyObject nameA='foo'/></MyContainer>");MyContainerClass myContainerA = (MyContainerClass) unmarshaller.unmarshal(aXml);System.out.println(myContainerA.getMyObject().getClass());StringReader bXml = new StringReader("<MyContainer><MyObject nameB='foo' attrFromB='bar'/></MyContainer>");MyContainerClass myContainerB = (MyContainerClass) unmarshaller.unmarshal(bXml);System.out.println(myContainerB.getMyObject().getClass());StringReader cXml = new StringReader("<MyContainer><MyObject nameC='foo' attrFromC='bar'/></MyContainer>");MyContainerClass myContainerC = (MyContainerClass) unmarshaller.unmarshal(cXml);System.out.println(myContainerC.getMyObject().getClass());}}

输出

[EL 警告]:2012-01-20 10:36:41.828--忽略类 [com.test.example.B] 上的属性 [name],因为没有为其生成属性.[EL 警告]:2012-01-20 10:36:41.828--忽略类 [com.test.example.C] 上的属性 [name],因为没有为其生成属性.com.test.example.A 类com.test.example.B 类com.test.example.C 类


<块引用>

第二个问题:另一个问题是我不知道 Jaxb 是否是能够像内部预期的那样覆盖 xml 属性名称XML 文件(@nameA、@nameB 和 nameC 都引用 A.name)是有办法吗?

您可以利用 XmlAdapter 来回答这个问题.这种方法也可以用来回答你的第一个问题:

适配器

包 com.test.example;导入 javax.xml.bind.annotation.XmlAttribute;导入 javax.xml.bind.annotation.adapters.XmlAdapter;公共类 AAdapter 扩展 XmlAdapter<AAdapter.AdaptedA, A>{@覆盖公共 AdaptedA 元帅(A a)抛出异常 {如果(空==一个){返回空值;}AdaptedA AdaptedA = 新的 AdaptedA();如果(C 的一个实例){C c = (C) a;改编A.nameC = c.getName();适应A.attrFromC = c.getAttrFromC();} else if(a instanceof B) {B b = (B) a;改编A.nameB = b.getName();适应A.attrFromB = b.getAttrFromB();} else if(a instanceof A) {改编A.nameA = a.getName();}返回适应A;}@覆盖public A unmarshal(AdaptedA adaptA) 抛出异常 {如果(空==适应A){返回空值;}如果(空!=适应A.attrFromC){C c = 新 C();c.setName(adaptedA.nameC);c.setAttrFromC(adaptedA.attrFromC);返回 c;}否则如果(空!=适应A.attrFromB){B b = 新 B();b.setName(adaptedA.nameB);b.setAttrFromB(adaptedA.attrFromB);返回 b;}A a = 新 A();a.setName(adaptedA.nameA);返回一个;}公共静态类 AdaptedA {@XmlAttribute 公共字符串名称A;@XmlAttribute public String nameB;@XmlAttribute public String nameC;@XmlAttribute public String attrFromB;@XmlAttribute public String attrFromC;}}

元数据 (oxm-2.xml)

<?xml version="1.0"?><xml绑定xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"包名=com.test.example"版本="2.3"><java 类型><java-type name="MyContainerClass" xml-accessor-type="NONE"><xml-root-element name="MyContainer"/><java 属性><xml-element java-attribute="myObject" name="MyObject"><xml-java-type-adapter value="com.test.example.AAdapter"/></xml-元素></java-属性></java 类型></java-types></xml绑定>

演示2

包 com.test.example;导入 java.io.StringReader;导入 java.util.*;导入 javax.xml.bind.*;导入 org.eclipse.persistence.jaxb.JAXBContextFactory;公共类 Demo2 {公共静态 void main(String[] args) 抛出异常 {映射<字符串,对象>properties = new HashMap();properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "com/test/example/oxm-2.xml");JAXBContext jc = JAXBContext.newInstance(new Class[] {MyContainerClass.class}, properties);解组器 unmarshaller = jc.createUnmarshaller();编组器编组器 = jc.createMarshaller();marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);StringReader aXml = new StringReader("<MyContainer><MyObject nameA='foo'/></MyContainer>");MyContainerClass myContainerA = (MyContainerClass) unmarshaller.unmarshal(aXml);System.out.println(myContainerA.getMyObject().getClass());marshaller.marshal(myContainerA,System.out);StringReader bXml = new StringReader("<MyContainer><MyObject nameB='foo' attrFromB='bar'/></MyContainer>");MyContainerClass myContainerB = (MyContainerClass) unmarshaller.unmarshal(bXml);System.out.println(myContainerB.getMyObject().getClass());marshaller.marshal(myContainerB,System.out);StringReader cXml = new StringReader("<MyContainer><MyObject nameC='foo' attrFromC='bar'/></MyContainer>");MyContainerClass myContainerC = (MyContainerClass) unmarshaller.unmarshal(cXml);System.out.println(myContainerC.getMyObject().getClass());marshaller.marshal(myContainerC, System.out);}}

输出

类 com.test.example.A<?xml 版本="1.0" 编码="UTF-8"?><我的容器><MyObject nameA="foo"/></我的容器>com.test.example.B 类<?xml 版本="1.0" 编码="UTF-8"?><我的容器><MyObject nameB="foo" attrFromB="bar"/></我的容器>com.test.example.C 类<?xml 版本="1.0" 编码="UTF-8"?><我的容器><MyObject nameC="foo" attrFromC="bar"/></我的容器>

I'm facing a marshalling/unmarshalling problem involving inheritance and polymorphism using MOXy's JAXB implementation and external metadata bindings file.

I have no control on the XML files or the model classes.

There are multiple classes inside the model that inherit other DTO classes. Here is an example of the environment I'm working in. This example is only here for some syntax purpose, the real environment involves nested inheritance, collections etc. :

Here is the class that will be inherited

  class A {

        private String name;

        public String getName(){
              return name;
        }

        public void setName(String value){
              name = value;
        }

  } 

Here is one inherited class

  class B extends A {

        private String attrFromB;

        public String getAttrFromB(){
              return attrFromB;
        }

        public void setAttrFromB(String value){
              attrFromB = value;
        }
  } 

And another

  class C extends A {

        private String attrFromC;

        public String getAttrFromC(){
              return attrFromC;
        }

        public void setAttrFromC(String value){
              attrFromC= value;
        }
  } 

Here is a container class

  class MyContainerClass{

        private A myObject;

        public A getMyObject(){
           return myObject;
        }

        public void setMyObject(A value){
           myObject = value;
        }
  }

Here is the XML that it should produce in the case of MyContainer containing A

  <MyContainer>
        <MyObject nameA="foo" />
  </MyContainer>

MyContainer containing B

  <MyContainer>
        <MyObject nameB="foo" attrFromB="bar" />
  </MyContainer>

And MyContainer containing C

  <MyContainer>
        <MyObject nameC="foo" attrFromC="bar" />
  </MyContainer>

So you can already see problems in the horizon...

Here is the mapping file that I would write :

  <?xml version="1.0"?>
     <xml-bindings 
        xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
        package-name="com.test.example"
        version="2.1">  

        <java-type name="A" xml-accessor-type="NONE">
           <xml-root-element name="MyObject" />
           <java-attributes>
              <xml-element java-attribute="name" xml-path="@nameA" />
           </java-attributes>
        </java-type>  

        <java-type name="B" xml-accessor-type="NONE">
           <xml-root-element name="MyObject" />
           <xml-see-also>
              com.test.example.A
           </xml.see.also>
           <java-attributes>
              <xml-element java-attribute="name" xml-path="@nameB" />
              <xml-element java-attribute="attrFromB" xml-path="@attrFromB" />
           </java-attributes>
        </java-type>

        <java-type name="C" xml-accessor-type="NONE">
           <xml-root-element name="MyObject" />
           <xml-see-also>
              com.test.example.A
           </xml.see.also>
           <java-attributes>
              <xml-element java-attribute="name" xml-path="@nameC" />
              <xml-element java-attribute="attrFromC" xml-path="@attrFromC" />
           </java-attributes>
        </java-type>

        <java-type name="MyContainer" xml-accessor-type="NONE">
           <xml-root-element name="MyContainer" />
           <java-attributes>
              <xml-element java-attribute="myObject" type="com.test.example.A" xml-path="MyObject" />
           </java-attributes>
        </java-type>

     </xml-bindings>


The first problem is that if I bind the classes like that, I get the following exception :

  [Exception [EclipseLink-44] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DescriptorException
  Exception Description: Missing class indicator field from database row [UnmarshalRecord()].

1st question : I understand that this is normal, Jaxb needs some way to determine the type of MyContaioner.myObject attribute. The problem is that I have no access to the incoming XML files, so I cant add xsi:type fields to them. Is there a way to determine a class based on the presence of a specific attribute in it ? regardless of it's value. If the source xml contains a @attrFromC attribute, I know the object should be of type C. If it contains attrFromB, it's B.


The second problem is that the "name" attribute doesn't exist inside B and C, so jaxb ignores em.

  --Ignoring attribute [name] on class [com.test.example.B] as no Property was generated for it.
  --Ignoring attribute [name] on class [com.test.example.C] as no Property was generated for it.

2nd question : The other problem is that I dont know if Jaxb is capable of overriding xml attribute names like it is expected inside the XML file (@nameA, @nameB and nameC all referring to A.name), is there a way to do it ?

Thanks in advance for your time.

解决方案

Below are the answers to your questions. The answer to question 2, is also an answer to question 1.


1st question : I understand that this is normal, Jaxb needs some way to determine the type of MyContaioner.myObject attribute. The problem is that I have no access to the incoming XML files, so I cant add xsi:type fields to them. Is there a way to determine a class based on the presence of a specific attribute in it ? regardless of it's value. If the source xml contains a @attrFromC attribute, I know the object should be of type C. If it contains attrFromB, it's B.

You can leverage the ClassExtractor extension in EclipseLink JAXB (MOXy) for this use case:

MyClassExtractor

A ClassExtractor is some code that you can implement to help MOXy determine which class it should instanitate. You are passed a Record and you can ask for the presence of the attributes at the current element by XPath to determine which class should be instantiated.

package com.test.example;

import org.eclipse.persistence.descriptors.ClassExtractor;
import org.eclipse.persistence.sessions.*;

public class MyClassExtractor extends ClassExtractor{

    @Override
    public Class<?> extractClassFromRow(Record record, Session session) {
        if(null != record.get("@attrFromB")) {
            return B.class;
        } else if(null != record.get("@attrFromC")) {
            return C.class;
        } else {
            return A.class;
        }
    }

}

Metadata (oxm.xml)

You can configure the ClassExtractor using the @XmlClassExtractor annotation. You can also do this via the external metadata file. I have adapted the one included in your question to include this:

<?xml version="1.0"?>
<xml-bindings 
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="com.test.example"
    version="2.3">
    <java-types>
        <java-type name="A" xml-accessor-type="NONE">
           <xml-class-extractor class="com.test.example.MyClassExtractor"/>
           <xml-root-element name="MyObject" />
           <java-attributes>
              <xml-attribute java-attribute="name" name="nameA" />
           </java-attributes>
        </java-type>  
        <java-type name="B" xml-accessor-type="NONE">
           <xml-root-element name="MyObject" />
           <java-attributes>
              <xml-attribute java-attribute="name" name="nameB" />
              <xml-attribute java-attribute="attrFromB"/>
           </java-attributes>
        </java-type>
        <java-type name="C" xml-accessor-type="NONE">
           <xml-root-element name="MyObject" />
           <java-attributes>
              <xml-attribute java-attribute="name" name="nameC" />
              <xml-attribute java-attribute="attrFromC"/>
           </java-attributes>
        </java-type>
        <java-type name="MyContainerClass" xml-accessor-type="NONE">
           <xml-root-element name="MyContainer" />
           <java-attributes>
              <xml-element java-attribute="myObject" name="MyObject" />
           </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Demo

The following demo code unmarshals each of the XML documents from your question, and outputs the type being held by the myObject property:

package com.test.example;

import java.io.StringReader;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "com/test/example/oxm.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {MyContainerClass.class}, properties);
        Unmarshaller unmarshaller = jc.createUnmarshaller();

        StringReader aXml = new StringReader("<MyContainer><MyObject nameA='foo'/></MyContainer>");
        MyContainerClass myContainerA = (MyContainerClass) unmarshaller.unmarshal(aXml);
        System.out.println(myContainerA.getMyObject().getClass());

        StringReader bXml = new StringReader("<MyContainer><MyObject nameB='foo' attrFromB='bar'/></MyContainer>");
        MyContainerClass myContainerB = (MyContainerClass) unmarshaller.unmarshal(bXml);
        System.out.println(myContainerB.getMyObject().getClass());

        StringReader cXml = new StringReader("<MyContainer><MyObject nameC='foo' attrFromC='bar'/></MyContainer>");
        MyContainerClass myContainerC = (MyContainerClass) unmarshaller.unmarshal(cXml);
        System.out.println(myContainerC.getMyObject().getClass());
    }

}

Output

[EL Warning]: 2012-01-20 10:36:41.828--Ignoring attribute [name] on class [com.test.example.B] as no Property was generated for it.
[EL Warning]: 2012-01-20 10:36:41.828--Ignoring attribute [name] on class [com.test.example.C] as no Property was generated for it.
class com.test.example.A
class com.test.example.B
class com.test.example.C


2nd question : The other problem is that I dont know if Jaxb is capable of overriding xml attribute names like it is expected inside the XML file (@nameA, @nameB and nameC all referring to A.name), is there a way to do it ?

You can leverage an XmlAdapter for this question. This approach can also be used to answer your first question:

AAdapter

package com.test.example;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class AAdapter extends XmlAdapter<AAdapter.AdaptedA, A> {

    @Override
    public AdaptedA marshal(A a) throws Exception {
        if(null == a) {
            return null;
        }
        AdaptedA adaptedA = new AdaptedA();
        if(a instanceof C) {
            C c = (C) a;
            adaptedA.nameC = c.getName();
            adaptedA.attrFromC = c.getAttrFromC();
        } else if(a instanceof B) {
            B b = (B) a;
            adaptedA.nameB = b.getName();
            adaptedA.attrFromB = b.getAttrFromB();
        } else if(a instanceof A) {
            adaptedA.nameA = a.getName();
        }
        return adaptedA;
    }

    @Override
    public A unmarshal(AdaptedA adaptedA) throws Exception {
        if(null == adaptedA) {
            return null;
        }
        if(null != adaptedA.attrFromC) {
            C c = new C();
            c.setName(adaptedA.nameC);
            c.setAttrFromC(adaptedA.attrFromC);
            return c;
        } else if(null != adaptedA.attrFromB) {
            B b = new B();
            b.setName(adaptedA.nameB);
            b.setAttrFromB(adaptedA.attrFromB);
            return b;
        } 
        A a = new A();
        a.setName(adaptedA.nameA);
        return a;
    }

    public static class AdaptedA {
        @XmlAttribute public String nameA;
        @XmlAttribute public String nameB;
        @XmlAttribute public String nameC;
        @XmlAttribute public String attrFromB;
        @XmlAttribute public String attrFromC;
    }

}

Metadata (oxm-2.xml)

<?xml version="1.0"?>
<xml-bindings 
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="com.test.example"
    version="2.3">
    <java-types>
        <java-type name="MyContainerClass" xml-accessor-type="NONE">
           <xml-root-element name="MyContainer" />
           <java-attributes>
              <xml-element java-attribute="myObject" name="MyObject">
                <xml-java-type-adapter value="com.test.example.AAdapter"/>
              </xml-element>
           </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Demo2

package com.test.example;

import java.io.StringReader;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;

public class Demo2 {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "com/test/example/oxm-2.xml");
        JAXBContext jc = JAXBContext.newInstance(new Class[] {MyContainerClass.class}, properties);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        StringReader aXml = new StringReader("<MyContainer><MyObject nameA='foo'/></MyContainer>");
        MyContainerClass myContainerA = (MyContainerClass) unmarshaller.unmarshal(aXml);
        System.out.println(myContainerA.getMyObject().getClass());
        marshaller.marshal(myContainerA, System.out);

        StringReader bXml = new StringReader("<MyContainer><MyObject nameB='foo' attrFromB='bar'/></MyContainer>");
        MyContainerClass myContainerB = (MyContainerClass) unmarshaller.unmarshal(bXml);
        System.out.println(myContainerB.getMyObject().getClass());
        marshaller.marshal(myContainerB, System.out);

        StringReader cXml = new StringReader("<MyContainer><MyObject nameC='foo' attrFromC='bar'/></MyContainer>");
        MyContainerClass myContainerC = (MyContainerClass) unmarshaller.unmarshal(cXml);
        System.out.println(myContainerC.getMyObject().getClass());
        marshaller.marshal(myContainerC, System.out);
    }

}

Output

class com.test.example.A
<?xml version="1.0" encoding="UTF-8"?>
<MyContainer>
   <MyObject nameA="foo"/>
</MyContainer>
class com.test.example.B
<?xml version="1.0" encoding="UTF-8"?>
<MyContainer>
   <MyObject nameB="foo" attrFromB="bar"/>
</MyContainer>
class com.test.example.C
<?xml version="1.0" encoding="UTF-8"?>
<MyContainer>
   <MyObject nameC="foo" attrFromC="bar"/>
</MyContainer>

这篇关于eclipselink/Moxy:基于类型的继承和属性名重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆