代码之家  ›  专栏  ›  技术社区  ›  rawat

JAXB将多态POJO封送到XML

  •  2
  • rawat  · 技术社区  · 7 年前

    我正在尝试使用JAXB封送类文件(带有注释)。低于 <profile-set> 它可以有不同的标签,例如。

    <organization-information-profile>
    <connection-profile>
    <user-information-profile>
    

    示例输出XML文件如下

    (一)

        <?xml version="1.0"?>
        <request version="2.0" principal="111" credentials="xxxxx">
          <target name="TestAPI" operation="create">
            <parameter>
              <organization>
                <qualified-name>some-qualified-name</qualified-name>
                <profile-set>
                  <name>TestOrg</name>
                  <organization-information-profile>
                    <name>Organization Information</name>
                    <qualified-name>/Organization Information</qualified-name>
                    <last-name>Test</last-name>
                    <address>some-address</address>
                    <city>my-city</city>
                    <province></province>
                    <postal-code>1111</postal-code>
                    <country>Timbaktu</country>
                    <phone-number-day>1111</phone-number-day>
                    <email-address>some@email.com</email-address>
                    <attribute name="PhoneNumber1">
                      <value context="organization">23333</value>
                    </attribute>
                    <attribute name="ShortName">
                      <value context="organization">my company</value>
                    </attribute>
                    <attribute name="TaxId">
                      <value context="organization">myorg</value>
                    </attribute>
                  </organization-information-profile>
                </profile-set>
              </organization>
            </parameter>
          </target>
    </request>
    

            <?xml version="1.0"?>
            <request version="2.0" principal="11111" credentials="xxxxx">
              <target name="TestAPI" operation="update">
                <parameter>
                  <organization>
                    <qualified-name>some-qualified-name</qualified-name>
                    <profile-set>
                      <name>TestOrg</name>
                      <connection-profile>
                        <qualified-name>some-qualified-name</qualified-name> 
                        <service>
                          <name>some service</name> 
                        </service>
                        <attribute name="att-1">
                          <value context="organization" segment="some-segment" subscript="524288">fill-the-value</value> 
                        </attribute>
                        <attribute name="att-2">
                          <value context="organization" segment="some-segment" subscript="524288">qedqwe</value> 
                        </attribute>            
                      </connection-profile>
                    </profile-set>
                  </organization>
                </parameter>
              </target>
            </request> 
    

    下面是代码(仅配置文件集)

     public static class ProfileSet
        {
            @XmlElement(name = "name")
            public String name;
    
            // innerPayLoad is template to store different profile objects
            @XmlJavaTypeAdapter(CustomAdaptor.class)
            @XmlElement
            public InnerPayLoad innerPayLoad;
    
            public ProfileSet(String name, InnerPayLoad innerPayLoad)
            {
                this.name = name;
                this.innerPayLoad = innerPayLoad;
            }
    
        }
    

    和自定义适配器

    public class CustomAdaptor extends XmlAdapter<String,InnerPayLoad<?>>
    {
    
    
        @Override
        public InnerPayLoad<?> unmarshal(String v) throws Exception
        {
            return null;
        }
    
        @Override
        public String marshal(InnerPayLoad<?> v) throws Exception
        {
             String value = TestCode.convertToXmlNoHeader(v.whichProfile,v.whichProfile.getClass());
    
             // after converting value becomes 
    
            //  <organization-information-profile>
            //      <name>Organization Information</name>
            //  </organization-information-profile> 
    
            return value;
        }
    }       
    

    但最终生成的XML与(a)for不相似 organization-information-profile

     <?xml version='1.0' encoding='UTF-8'?>
    <request version="2.0" principle="11111" credentials="xxxxx">
      <target name="TestAPI" operation="create">
        <parameter>
          <organization>
            <qualified-name>newOrg</qualified-name>
            <profile-set>
              <innerPayLoad>&lt;organization-information-profile>
        &lt;name>Organization Information&lt;/name>
    &lt;/organization-information-profile></innerPayLoad>
              <name>testOrg</name>
            </profile-set>
          </organization>
        </parameter>
      </target>
    </request>
    

    是否可以移除 <innerPayLoad> 标记并插入CustomAdapter封送处理函数返回值?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Thomas Fritsch    7 年前

    您不需要为您的系统中的各种概要文件类型编写自定义适配器 ProfileSet

    相反,要处理这种混合的XML内容,规范方法是这样的。

    轮廓集 类,您应该定义多态Java属性 profile <organization.information-profile> , <connection-profile> 或 <user-information-profile> (我更喜欢这个名字 轮廓 innerPayload 这些XML元素名和Java类之间的映射已经完成 通过使用 @XmlElements 注释。

    @XmlAccessorType(XmlAccessType.FIELD)
    public class ProfileSet {
    
        @XmlElement(name = "name")
        private String name;
    
        // template to store different profile objects    
        @XmlElements({
            @XmlElement(name = "organization-information-profile", type = OrganizationInfomationProfile.class),
            @XmlElement(name = "connection-profile", type = ConnectionProfile.class),
            @XmlElement(name = "user-information-profile", type = UserInformationProfile.class)
        })
        private Profile profile;
    
        // default constructor used by JAXB unmarshaller
        public ProfileSet() {
        }
    
        public ProfileSet(String name, Profile profile) {
            this.name = name;
            this.profile = profile;
        }
     }
    

    你需要一个抽象的超类 Profile

    @XmlAccessorType(XmlAccessType.FIELD)
    public abstract class Profile {
    
        @XmlElement
        private String name;
    
        @XmlElement(name = "attribute")
        private List<Attribute> attributes;
    }
    

    你有一个子类 OrganizationInformationProfile 代表 <organization-information-profile> 要素

    @XmlAccessorType(XmlAccessType.FIELD)
    public class OrganizationInfomationProfile extends Profile {
    
        @XmlElement(name = "qualified-name")
        private String qualifiedName;
    
        @XmlElement(name = "last-name")
        private String lastName;
    
        @XmlElement(name = "address")
        private String address;
    
        // ... other properties
    
    }
    

    ConnectionProfile 代表 <连接配置文件> 要素

    @XmlAccessorType(XmlAccessType.FIELD)
    public class ConnectionProfile extends Profile {
    
        @XmlElement(name = "service")
        private Service service;
    }
    

    还有另一个亚类 UserInformationProfile 代表 <用户信息配置文件> 元素。

    通过使用上述方法,您可以解组XML示例