Reputation: 41
I am using Jackson to deserialize XML. It works fine when serializing into a list when there are no other elements in between, but if i insert some other field in the middle somewhere, it seems to only put the things below the field into my list. See below only the ProductA objects after the Product B tag are being included.
I set a breakpoint to get the JsonNode object using the xmlMapper readTree method, and the properties above the ProductB tag are not there in the node tree.
Is there a way using jackson (or another library) to get all ProductA elements inside the Warehouse element, independent of the ordering of the Warehouse child elements?
public class Warehouse {
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "ProductA")
private List<ProductA> productAList;
@JacksonXmlProperty(localName = "ProductB")
private String productB;
//getters and setters
}
public class ProductA {
@JacksonXmlProperty(localName = "PropA")
private String propA;
//getters and setters
}
<Warehouse>
<ProductA>
<propA>abc</propA>
</ProductA>
<ProductA>
<propA>abc</propA>
</ProductA>
<ProductB>def</ProductB>
<ProductA>
<propA>abc</propA>
</ProductA>
</Warehouse>
Upvotes: 4
Views: 1354
Reputation: 626
Change your Warehouse class to use a method just for setting the value of productAList from XML, and remove the annotations from the productAList property.
@JsonSetter(value = "ProductA")
public void setProductAListFromXml(ProductA productA) {
if (this.productAList == null) {
this.productAList = new ArrayList<ProductA>();
}
this.productAList.add(productA);
}
Here is the full Warehouse class:
@JacksonXmlRootElement(localName = "Warehouse")
public class Warehouse {
private List<ProductA> productAList;
@JacksonXmlProperty(localName = "ProductB")
private String productB;
public List<ProductA> getProductAList() {
return productAList;
}
public void setProductAList(List<ProductA> productAList) {
this.productAList = productAList;
}
@JsonSetter(value = "ProductA")
public void setProductAListFromXml(ProductA productA) {
if (this.productAList == null) {
this.productAList = new ArrayList<ProductA>();
}
this.productAList.add(productA);
}
public String getProductB() {
return productB;
}
public List<ProductA> getProductA() {
return productAList;
}
}
Using the class like this:
String str = "<Warehouse>\r\n" +
" <ProductA>\r\n" +
" <propA>abc</propA>\r\n" +
" </ProductA>\r\n" +
" <ProductA>\r\n" +
" <propA>abc</propA>\r\n" +
" </ProductA>\r\n" +
" <ProductB>def</ProductB>\r\n" +
" <ProductA>\r\n" +
" <propA>abc</propA>\r\n" +
" </ProductA>\r\n" +
"</Warehouse>";
XmlMapper mapper = new XmlMapper();
Warehouse warehouse = mapper.readValue(str, Warehouse.class);
System.out.println(warehouse.getProductB());
System.out.println(warehouse.getProductA());
Produces this output:
def
[ProductA [propA=abc], ProductA [propA=abc], ProductA [propA=abc]]
Upvotes: 3