如何修复 Jaxb 的 xmlMapper "Multiple fields representing property "PS"" 问题?
How to fix xmlMapper "Multiple fields representing property "PS"" issue with Jaxb?
我使用 Jaxb 从 xsd:
生成了一个 Jar 文件
CustomObject inputRequest = xmlMapper.readValue(input, CustomObject.class);
我收到的错误消息是:
com.fasterxml.jackson.databind.JsonMappingException: Multiple fields
representing property "PS": OrderLineType#pS vs OrderLineType#pSV5 at
[Source: (StringReader); line: 1, column: 1]
而我的 class 是:
@XmlElement(name = "PS", namespace = "financetypes:defn:v4")
protected financetypes.v4.PSType pS;
@XmlElement(name = "PS", namespace = "financetypes:defn:v5")
protected financetypes.v5.PSType pSV5;
它们具有相同的名称,但命名空间不同。
xmlmapper 是否可以处理同名不同命名空间的 XmlElement?
如果是,我该如何解决?如果没有,我该怎么办?
我正在从 jenkin 构建 jar 文件。有没有我可以用来解决这个问题的插件?
谢谢!
这是我的 xsd
v4.xsd
<!--Begin Definition: Complex Type: PriceStructureType-->
<xs:complexType name="PriceStructureType">
<xs:sequence>
<xs:element name="PriceModel" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
TODO: Add valid items...
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element ref="finance:SourceSystemPrice" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="ComponentPrice" type="finance:ComponentListType" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="PriceStructure" type="finance:PriceStructureType"/>
<!--End Definition: Complex Type: PriceStructureType-->
v5.xsd
<!--Begin Definition: Complex Type: PriceStructureType-->
<xs:complexType name="PriceStructureType">
<xs:sequence>
<xs:element name="PriceModel" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
TODO: Add valid items...
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element ref="finance:SourceSystemPrice" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="ComponentPrice" type="finance:ComponentListType" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="PriceStructure" type="finance:PriceStructureType"/>
<!--End Definition: Complex Type: PriceStructureType-->
common.xsd
xmlns:finance="urn:financetypes:defn:v4"
xmlns:finance_v5="urn:financetypes:defn:v5"
<xs:import namespace="urn:financetypes:defn:v4" schemaLocation="financetypes.v4.xsd"/>
<xs:import namespace="urn:financetypes:defn:v5" schemaLocation="financetypes.v5.xsd"/>
<xs:choice>
<xs:element ref="finance:PriceStructure" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">
Price Structure itemizes the price components of this OrderLine. Pricing
is a integral part of the Sales Order record.
This should be a required element for a sales order, but it is marked
as optional for backward compatibility.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element ref="finance_v5:PriceStructure" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">
Price Structure itemizes the price components of this OrderLine. Pricing
is a integral part of the Sales Order record.
This should be a required element for a sales order, but it is marked
as optional for backward compatibility.
</xs:documentation>
<xs:appinfo>
<jaxb:property name="PriceStructureV5"/>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:choice>
你可以做到这一点。对于包含这两个元素的根 class:
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlElement(name = "PS", namespace = "financetypes:defn:v4")
protected financetypes.v4.PSType pS;
@XmlElement(name = "PS", namespace = "financetypes:defn:v5")
protected financetypes.v5.PSType pSV5;
}
您可以像这样创建具有不同版本的 classes:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "v4PS", namespace = "financetypes:defn:v4")
public class PSType {
@XmlValue
private String value;
}
和:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "v5PS", namespace = "financetypes:defn:v5")
public class PSType {
@XmlValue
private String value;
}
示例xml如下:
<root xmlns:v4="financetypes:defn:v4" xmlns:v5="financetypes:defn:v5">
<v4:PS>version 4</v4:PS>
<v5:PS>version 5</v5:PS>
</root>
您将能够正确解组。
更新回复评论:
您使用 xsd 生成 classes。你没有提供 xsd 所以我假设你不被允许。我创建了一个 xsd 来生成您在问题中显示的 classes。 namespace.xsd 看起来像这样:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:v4="financetypes:defn:v4" xmlns:v5="financetypes:defn:v5">
<xs:element name="root">
<xs:complexType>
<xs:all>
<xs:element name="v4PSType" type="PSTypev4" />
<xs:element name="v5PSType" type="PSTypev5" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:complexType name="PSTypev4">
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="PSTypev5">
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
</xs:schema>
那么您的绑定将是:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:annox="http://annox.dev.java.net"
jaxb:extensionBindingPrefixes="xjc">
<jaxb:bindings schemaLocation="../xsd/namespaces.xsd">
<jaxb:bindings node="//xs:complexType[@name='PSTypev4']">
<annox:annotate target = "class">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlType" name="v4PSType" namespace="financetypes:defn:v4" />
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="//xs:complexType[@name='PSTypev5']">
<annox:annotate target = "class">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlType" name="v5PSType" namespace="financetypes:defn:v5" />
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[@name='root']//xs:complexType//xs:all//xs:element[@name='v5PSType']">
<annox:annotate target = "field">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" name="PS" namespace="financetypes:defn:v5" />
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[@name='root']//xs:complexType//xs:all//xs:element[@name='v4PSType']">
<annox:annotate target = "field">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" name="PS" namespace="financetypes:defn:v4" />
</annox:annotate>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
然后你会得到 classes 作为我的答案。
我使用 Jaxb 从 xsd:
生成了一个 Jar 文件CustomObject inputRequest = xmlMapper.readValue(input, CustomObject.class);
我收到的错误消息是:
com.fasterxml.jackson.databind.JsonMappingException: Multiple fields representing property "PS": OrderLineType#pS vs OrderLineType#pSV5 at [Source: (StringReader); line: 1, column: 1]
而我的 class 是:
@XmlElement(name = "PS", namespace = "financetypes:defn:v4")
protected financetypes.v4.PSType pS;
@XmlElement(name = "PS", namespace = "financetypes:defn:v5")
protected financetypes.v5.PSType pSV5;
它们具有相同的名称,但命名空间不同。
xmlmapper 是否可以处理同名不同命名空间的 XmlElement?
如果是,我该如何解决?如果没有,我该怎么办?
我正在从 jenkin 构建 jar 文件。有没有我可以用来解决这个问题的插件?
谢谢!
这是我的 xsd v4.xsd
<!--Begin Definition: Complex Type: PriceStructureType-->
<xs:complexType name="PriceStructureType">
<xs:sequence>
<xs:element name="PriceModel" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
TODO: Add valid items...
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element ref="finance:SourceSystemPrice" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="ComponentPrice" type="finance:ComponentListType" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="PriceStructure" type="finance:PriceStructureType"/>
<!--End Definition: Complex Type: PriceStructureType-->
v5.xsd
<!--Begin Definition: Complex Type: PriceStructureType-->
<xs:complexType name="PriceStructureType">
<xs:sequence>
<xs:element name="PriceModel" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
TODO: Add valid items...
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element ref="finance:SourceSystemPrice" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="ComponentPrice" type="finance:ComponentListType" minOccurs="0">
<xs:annotation>
<xs:documentation>
Will be required in future...
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="PriceStructure" type="finance:PriceStructureType"/>
<!--End Definition: Complex Type: PriceStructureType-->
common.xsd
xmlns:finance="urn:financetypes:defn:v4"
xmlns:finance_v5="urn:financetypes:defn:v5"
<xs:import namespace="urn:financetypes:defn:v4" schemaLocation="financetypes.v4.xsd"/>
<xs:import namespace="urn:financetypes:defn:v5" schemaLocation="financetypes.v5.xsd"/>
<xs:choice>
<xs:element ref="finance:PriceStructure" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">
Price Structure itemizes the price components of this OrderLine. Pricing
is a integral part of the Sales Order record.
This should be a required element for a sales order, but it is marked
as optional for backward compatibility.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element ref="finance_v5:PriceStructure" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">
Price Structure itemizes the price components of this OrderLine. Pricing
is a integral part of the Sales Order record.
This should be a required element for a sales order, but it is marked
as optional for backward compatibility.
</xs:documentation>
<xs:appinfo>
<jaxb:property name="PriceStructureV5"/>
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:choice>
你可以做到这一点。对于包含这两个元素的根 class:
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlElement(name = "PS", namespace = "financetypes:defn:v4")
protected financetypes.v4.PSType pS;
@XmlElement(name = "PS", namespace = "financetypes:defn:v5")
protected financetypes.v5.PSType pSV5;
}
您可以像这样创建具有不同版本的 classes:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "v4PS", namespace = "financetypes:defn:v4")
public class PSType {
@XmlValue
private String value;
}
和:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "v5PS", namespace = "financetypes:defn:v5")
public class PSType {
@XmlValue
private String value;
}
示例xml如下:
<root xmlns:v4="financetypes:defn:v4" xmlns:v5="financetypes:defn:v5">
<v4:PS>version 4</v4:PS>
<v5:PS>version 5</v5:PS>
</root>
您将能够正确解组。
更新回复评论:
您使用 xsd 生成 classes。你没有提供 xsd 所以我假设你不被允许。我创建了一个 xsd 来生成您在问题中显示的 classes。 namespace.xsd 看起来像这样:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:v4="financetypes:defn:v4" xmlns:v5="financetypes:defn:v5">
<xs:element name="root">
<xs:complexType>
<xs:all>
<xs:element name="v4PSType" type="PSTypev4" />
<xs:element name="v5PSType" type="PSTypev5" />
</xs:all>
</xs:complexType>
</xs:element>
<xs:complexType name="PSTypev4">
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="PSTypev5">
<xs:simpleContent>
<xs:extension base="xs:string" />
</xs:simpleContent>
</xs:complexType>
</xs:schema>
那么您的绑定将是:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:annox="http://annox.dev.java.net"
jaxb:extensionBindingPrefixes="xjc">
<jaxb:bindings schemaLocation="../xsd/namespaces.xsd">
<jaxb:bindings node="//xs:complexType[@name='PSTypev4']">
<annox:annotate target = "class">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlType" name="v4PSType" namespace="financetypes:defn:v4" />
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="//xs:complexType[@name='PSTypev5']">
<annox:annotate target = "class">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlType" name="v5PSType" namespace="financetypes:defn:v5" />
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[@name='root']//xs:complexType//xs:all//xs:element[@name='v5PSType']">
<annox:annotate target = "field">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" name="PS" namespace="financetypes:defn:v5" />
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[@name='root']//xs:complexType//xs:all//xs:element[@name='v4PSType']">
<annox:annotate target = "field">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlElement" name="PS" namespace="financetypes:defn:v4" />
</annox:annotate>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
然后你会得到 classes 作为我的答案。