Вот два примера XML, который я пытаюсь разобрать с помощью JAXB / EclipseLink:
Пример. 1:
<?xml version="1.0" encoding="ISO-8859-1"?>
<responseMessage requestedService="warehouses.activeProducts" responseStatus="1" >
<responseBody>
<entities name="Product">
<entity>
<PRODUCTID>09941234504</PRODUCTID>
<PRODUCTDESCRIPTION>
<![CDATA[SOME PRODUCT DESCRIPTION 1]]>
</PRODUCTDESCRIPTION>
<ACTIVE>
<![CDATA[S]]>
</ACTIVE>
</entity>
<entity>
<PRODUCTID>09941234182</PRODUCTID>
<PRODUCTDESCRIPTION>
<![CDATA[SOME PRODUCT DESCRIPTION 2]]>
</PRODUCTDESCRIPTION>
<ACTIVE>
<![CDATA[S]]>
</ACTIVE>
</entity>
</entities>
</responseBody>
</responseMessage>
Пример. 2:
<?xml version="1.0" encoding="ISO-8859-1"?>
<responseMessage requestedService="warehouses.availableLocations" responseStatus="1" >
<responseBody>
<entities name="Location">
<entity>
<LOCATIONID>10925243325</LOCATIONID>
<ACTIVE>
<![CDATA[S]]>
</ACTIVE>
</entity>
<entity>
<LOCATIONID>10925243325</LOCATIONID>
<ACTIVE>
<![CDATA[S]]>
</ACTIVE>
</entity>
</entities>
</responseBody>
</responseMessage>
Мы имеем представление о том, что находится внутри списка <entities></entities>
, из-за его атрибута name
(name="Product"
и name="Location"
).
Моя реализация что-то вроде этого:
serviceCallResponse_products = ... input stream of the service's call for products...
serviceCallResponse_locations = ... input stream of the service's call for locations...
Class[] classes = new Class[]{
ResponseMessage.class, // @XmlRootElement(name = "responseMessage")
ResponseBody.class, // @XmlRootElement(name = "responseBody")
Entities.class // @XmlRootElement(name = "entities") - the list wrapper
Product.class, // @XmlRootElement(name = "entity")
Location.class, // @XmlRootElement(name = "entity")
};
JAXBContext createContext = JAXBContext.newInstance(classes);
Unmarshaller createUnmarshaller = createContext.createUnmarshaller();
// This works!
ResponseMessage<Location> = r = (ResponseMessage<Location>) createUnmarshaller
.unmarshal(serviceCallResponse_locations);
// This does not work. I get a ResponseMessage<Location> instead of ResponseMessage<Product>
ResponseMessage<Product> = r = (ResponseMessage<Product>) createUnmarshaller
.unmarshal(serviceCallResponse_products);
и вот мои объекты:
@XmlRootElement(name = "responseMessage")
public class ResponseMessage<T> {
public ResponseMessage() {
responseBody = new ResponseBody<>();
}
@XmlElement
private ResponseBody<T> responseBody;
}
@XmlRootElement(name = "responseBody")
public class ResponseBody<T> {
public ResponseBody() {
this.entities = new Entities<>();
}
@XmlElement
private Entities<T> entities;
}
@XmlRootElement(name = "entities")
public class Entities<T> {
public Entities() {
this.entityList = new ArrayList<T>();
}
private String name;
List<T> entityList;
@XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlAnyElement(lax = true)
public List<T> getEntityList() {
return entityList;
}
public void setEntityList(List<T> entityList) {
this.entityList = entityList;
}
}
@XmlRootElement(name = "entity")
public class Product {
@XmlElement(name = "PRODUCTID")
private String productId;
@XmlElement(name = "PRODUCTDESCRIPTION")
private String productDescription;
@XmlElement(name = "ACTIVE")
private String active;
}
@XmlRootElement(name = "entity")
public class Location {
@XmlElement(name = "LOCATIONID")
private String productId;
@XmlElement(name = "ACTIVE")
private String active;
}
Проблема заключается в том, как правильно демаршировать список объектов в список объектов параметризованного типа, либо Product
или Location
. Поскольку и Product
, и Location
имеют одно и то же имя элемента («сущность»), JAXB будет анализировать сопоставленный элемент xml с последним зарегистрированным (в данном случае Location
).
Несмотря на то, что я использую JAXB непосредственно здесь, мое приложение использует OpenFeign для выполнения запросов и оборачивает JaxB в класс кодировщика / декодера.
Есть ли лучший (или правильный) способ сопоставить этот сценарий / сущности?
Есть ли какой-нибудь способ "подсказки" JaxB для создания экземпляра объекта в зависимости от атрибута его родителя ("name")?
Спасибо!