首页 > 解决方案 > Jackson xml反序列化 - 序列化为一个列表,其中包含任意元素

问题描述

我正在使用 Jackson 反序列化 XML。当中间没有其他元素时,它在序列化到列表中时工作正常,但是如果我在中间的某个地方插入一些其他字段,它似乎只会将字段下方的内容放入我的列表中。请参见下面仅包含 Product B 标记后的 ProductA 对象。

我使用xmlMapper readTree方法设置了一个断点来获取JsonNode对象,而ProductB标签上面的属性在节点树中是没有的。

有没有办法使用杰克逊(或其他库)来获取 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>

标签: javaxmljacksonxml-parsing

解决方案


更改您的 Warehouse 类以使用仅用于从 XML 设置 productAList 值的方法,并从 productAList 属性中删除注释。

@JsonSetter(value =  "ProductA")
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;
    }

    @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;
    }
}

使用这样的类:

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]]

推荐阅读