[英]JAXB marshal polymorphic POJO to XML
I am trying to use JAXB to marshal class file(with annotations).我正在尝试使用 JAXB 来封送类文件(带注释)。 Under
<profile-set>
it can have different tags for eg在
<profile-set>
它可以有不同的标签,例如
<organization-information-profile>
<connection-profile>
<user-information-profile>
Sample output XML files are as below示例输出 XML 文件如下
a)一种)
<?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>
b) b)
<?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>
Below is the code (only profile-set)下面是代码(仅配置文件集)
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;
}
}
And CustomAdaptor和自定义适配器
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;
}
}
But the final XML produced is not similar to (a) for organization-information-profile
但最终生成的 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><organization-information-profile>
<name>Organization Information</name>
</organization-information-profile></innerPayLoad>
<name>testOrg</name>
</profile-set>
</organization>
</parameter>
</target>
</request>
Is it possible to remove <innerPayLoad>
tag and just insert with CustomAdaptor marshal function return value?是否可以删除
<innerPayLoad>
标记并仅插入 CustomAdaptor marshal 函数返回值?
Appreciate help and hints to solve this issue.感谢帮助和提示来解决这个问题。
You don't need to write a custom adapter for the various profile types within your ProfileSet
.您不需要为
ProfileSet
的各种配置文件类型编写自定义适配器。
Instead, to handle such mixed XML Content the canonical approach goes like this.相反,为了处理这种混合的 XML 内容,规范的方法是这样的。
In your ProfileSet
class you should define a polymorphic Java property profile
which can take the contents of a <organization.information-profile>
, <connection-profile>
or <user-information-profile>
element.在您的
ProfileSet
类中,您应该定义一个多态 Java 属性profile
,它可以采用<organization.information-profile>
、 <connection-profile>
或<user-information-profile>
元素的内容。 (I preferred the name profile
here instead of innerPayload
). (我更喜欢这里的名称
profile
而不是innerPayload
)。 The mapping between these XML element names and Java classes is done by using the @XmlElements
annotation.这些 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;
}
}
You need an abstract super-class Profile
containing only the properties common to all kinds of profiles:您需要一个抽象的超类
Profile
,它只包含所有类型的Profile
共有的属性:
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class Profile {
@XmlElement
private String name;
@XmlElement(name = "attribute")
private List<Attribute> attributes;
}
You have one subclass OrganizationInformationProfile
for representing the <organization-information-profile>
element您有一个子类
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
}
and another subclass ConnectionProfile
for representing the <connection-profile>
element和另一个用于表示
<connection-profile>
元素的子类ConnectionProfile
@XmlAccessorType(XmlAccessType.FIELD)
public class ConnectionProfile extends Profile {
@XmlElement(name = "service")
private Service service;
}
and yet another subclass UserInformationProfile
for representing the <user-information-profile>
element.以及另一个用于表示
<user-information-profile>
元素的子类UserInformationProfile
。
By using the above approach you can unmarshal your XML examples and get the same output again when marshalling.通过使用上述方法,您可以解组 XML 示例并在编组时再次获得相同的输出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.