英文:
Jackson xml deserialization - serialize to a list with arbitrary elements in between
问题
以下是翻译好的内容:
我正在使用Jackson来反序列化XML。在序列化为列表时,如果中间插入了其他元素,它可以正常工作,但是如果我在中间的某个位置插入了一些其他字段,它似乎只会将字段下面的内容放入我的列表中。请看下面,仅在Product B标签之后的ProductA对象被包括进来。
我设置了断点,使用xmlMapper的readTree方法获取JsonNode对象,但是ProductB标签上面的属性在节点树中不存在。
是否有一种使用jackson(或另一个库)的方式,可以获取Warehouse元素内的所有ProductA元素,而不考虑Warehouse子元素的顺序?
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>
英文:
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>
答案1
得分: 2
将你的 Warehouse 类修改为仅使用一个方法来从 XML 设置 productAList 的值,并从 productAList 属性中移除注释。
public void setProductAListFromXml(ProductA productA) {
if (this.productAList == null) {
this.productAList = new ArrayList<ProductA>();
}
this.productAList.add(productA);
}
以下是完整的 Warehouse 类:
@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;
}
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;
}
}
使用该类的方式如下:
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());
生成以下输出:
def
[ProductA [propA=abc], ProductA [propA=abc], ProductA [propA=abc]]
英文:
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]]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论