【问题标题】:Jackson XMLWrapper failing to deserialize this xml into pojo?Jackson XMLWrapper 未能将此 xml 反序列化为 pojo?
【发布时间】:2021-07-05 06:15:35
【问题描述】:

考虑下面给定的xml:

<?xml version="1.0"?>
<Records>
    <Record>
        <Prop name="commerce">sku1</Prop>
        <Prop name="commerce">sku2</Prop>
        <Prop name="commerce">sku3</Prop>
        <Prop name="commerce">sku4</Prop>
    </Record>
    <Record>
        <Prop name="commerce">sku10</Prop>
        <Prop name="commerce">sku20</Prop>
        <Prop name="commerce">sku30</Prop>
        <Prop name="commerce">sku40</Prop>
    </Record>
</Records>

现在考虑一下我创建的这些 Pojos(为简洁起见,删除了 getter 和 setter)。

public class Records {
    private List<Record> records;
}

public class Record {
    private List<Prop> props;
}

public class Prop {
    // I want to capture name attribute
    private String name;
    // But I also want to capture what comes inside Prop element as well. This would then have values like sku1, sku2 etc
    private String text;
}

现在我有了像这样使用 XMLWrapper 的代码。

File file = ResourceUtils.getFile("classpath:sample.xml"); // the above XML is sample.xml
XmlMapper xmlMapper = XmlMapper.builder().build();
Records records = xmlMapper.readValue(file, Records.class); // this line is failing

但是我遇到了这样的错误

Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Record" (class com.example.demo.model.xml.Records), not marked as ignorable (one known property: "records"])

【问题讨论】:

  • 应该是 @XmlElement(name = "Record") private List&lt;Record&gt; records; 以匹配元素名称。 Prop 的主体相同

标签: java xml jackson xml-deserialization fasterxml


【解决方案1】:

即使没有 XML 注释(大部分情况下),这个解决方案似乎也适合我。为后代张贴。

第 1 步:禁用换行。

File file = ResourceUtils.getFile("classpath:sample.xml"); 
XmlMapper xmlMapper = XmlMapper.builder().defaultUseWrapper(false).build();
Records records = xmlMapper.readValue(file, Records.class);

第 2 步:使用 JsonProperty 注释更新 pojos(唯一的例外是使用 @JacksonXmlText 获取内部值。为简洁起见,请注意删除 setter 和 getter。

public class Records {
    @JsonProperty("Record")
    private List<Record> records;
}

public class Record {
    @JsonProperty("Prop")
    private List<Prop> props;
}

public class Prop {
    @JsonProperty("name")
    private String name;

    @JacksonXmlText
    private String text;
}

以上对我有用。

【讨论】:

    【解决方案2】:

    您必须将@JacksonXmlProperty 注释与指示包装器元素的@JacksonXmlElementWrapper 注释结合使用Collection:在这种情况下,可选属性useWrapping 设置为false 明确禁用包装:

    public class Records {
        @JacksonXmlProperty(localName = "Record")
        @JacksonXmlElementWrapper(useWrapping = false)
        private List<Record> records;
    }
    
    public class Record {
        @JacksonXmlProperty(localName = "Prop")
        @JacksonXmlElementWrapper(useWrapping = false)
        private List<Prop> props;
    }
    
    public class Prop {
        //<Prop name="commerce">sku1</Prop> name is an attribute with value commerce
        @JacksonXmlProperty(localName= "name", isAttribute = true)
        private String name;
        
        //<Prop name="commerce">sku1</Prop> sku1 is the text inside the Prop tags
        @JacksonXmlText
        private String text;
    }
    

    【讨论】:

    • 感谢您的解决方案。有用。即使没有这些注释中的一些并且仅使用@JsonProperty,我也能够使其正常工作。不知道如何,但它工作。发布了是否有人对未来感兴趣的答案。
    • @theprogrammer 欢迎您。我看到了您的解决方案,它包含的代码比我的少,如果类与您的问题中包含的类类似,则使用 defaultUseWrapper(false) 全局禁用解包器肯定是最佳解决方案。如果您有不同的类模型,您可能应该在本地而不是更全局地注释每个类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-22
    • 2019-01-19
    • 1970-01-01
    • 2023-02-08
    • 2019-07-19
    • 1970-01-01
    • 2012-04-07
    相关资源
    最近更新 更多