Jackson XML反序列化 – 序列化为一个中间带有任意元素的列表

huangapple go评论63阅读模式
英文:

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 = &quot;ProductA&quot;)
private List&lt;ProductA&gt; productAList;

@JacksonXmlProperty(localName = &quot;ProductB&quot;)
private String productB;
//getters and setters

}
public class ProductA {
@JacksonXmlProperty(localName = &quot;PropA&quot;)
private String propA;

//getters and setters
}
&lt;Warehouse&gt;
 &lt;ProductA&gt;
  &lt;propA&gt;abc&lt;/propA&gt;
 &lt;/ProductA&gt;
 &lt;ProductA&gt;
  &lt;propA&gt;abc&lt;/propA&gt;
 &lt;/ProductA&gt;
 &lt;ProductB&gt;def&lt;/ProductB&gt;
 &lt;ProductA&gt;
  &lt;propA&gt;abc&lt;/propA&gt;
 &lt;/ProductA&gt;
&lt;/Warehouse&gt;

答案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 =  &quot;ProductA&quot;)
public void setProductAListFromXml(ProductA productA) {
    if (this.productAList == null) {
        this.productAList = new ArrayList&lt;ProductA&gt;();
    } 
    this.productAList.add(productA);
}

Here is the full Warehouse class:

@JacksonXmlRootElement(localName = &quot;Warehouse&quot;)
public class Warehouse {
    private List&lt;ProductA&gt; productAList;

    @JacksonXmlProperty(localName = &quot;ProductB&quot;)
    private String productB;

    public List&lt;ProductA&gt; getProductAList() {
        return productAList;
    }

    public void setProductAList(List&lt;ProductA&gt; productAList) {
        this.productAList = productAList;
    }

    @JsonSetter(value =  &quot;ProductA&quot;)
    public void setProductAListFromXml(ProductA productA) {
        if (this.productAList == null) {
            this.productAList = new ArrayList&lt;ProductA&gt;();
        } 
        this.productAList.add(productA);
    }
    
    public String getProductB() {
        return productB;
    }
    
    public List&lt;ProductA&gt; getProductA() {
        return productAList;
    }
}

Using the class like this:

String str = &quot;&lt;Warehouse&gt;\r\n&quot; + 
                &quot; &lt;ProductA&gt;\r\n&quot; + 
                &quot;  &lt;propA&gt;abc&lt;/propA&gt;\r\n&quot; + 
                &quot; &lt;/ProductA&gt;\r\n&quot; + 
                &quot; &lt;ProductA&gt;\r\n&quot; + 
                &quot;  &lt;propA&gt;abc&lt;/propA&gt;\r\n&quot; + 
                &quot; &lt;/ProductA&gt;\r\n&quot; + 
                &quot; &lt;ProductB&gt;def&lt;/ProductB&gt;\r\n&quot; + 
                &quot; &lt;ProductA&gt;\r\n&quot; + 
                &quot;  &lt;propA&gt;abc&lt;/propA&gt;\r\n&quot; + 
                &quot; &lt;/ProductA&gt;\r\n&quot; + 
                &quot;&lt;/Warehouse&gt;&quot;;
        
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]]

huangapple
  • 本文由 发表于 2020年7月25日 05:46:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/63081883.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定