1. 概述

上一篇文章中,我们学习了如何使用XStream将Java对象序列化为XML。在本教程中,我们将学习如何执行相反的操作:将 XML 反序列化为 Java 对象。这些任务可以使用注释或以编程方式完成。

要了解设置XStream及其依赖项的基本要求,请参考之前的文章。

2. 从 XML 反序列化对象

首先,假设我们有以下 XML:

<com.baeldung.pojo.Customer>
    <firstName>John</firstName>
    <lastName>Doe</lastName>
    <dob>1986-02-14 03:46:16.381 UTC</dob>
</com.baeldung.pojo.Customer>

我们需要将其转换为 Java Customer 对象:

public class Customer {
 
    private String firstName;
    private String lastName;
    private Date dob;
 
    // standard setters and getters
}

XML 可以通过多种方式输入,包括 FileInputStreamReaderString 。为简单起见,我们假设上面的 XML 位于 String 对象中。

Customer convertedCustomer = (Customer) xstream.fromXML(customerXmlString);
Assert.assertTrue(convertedCustomer.getFirstName().equals("John"));

3. 别名

在第一个示例中,XML 在最外面的 XML 标记中具有类的完全限定名称,与 Customer 类的位置相匹配。通过此设置,XStream 可以轻松地将 XML 转换为我们的对象,而无需任何额外的配置。但我们并不总是具备这些条件。我们可能无法控制 XML 标记命名,或者我们可能决定为字段添加别名。

例如,假设我们修改了 XML,不使用外部标记的完全限定类名:

<customer>
    <firstName>John</firstName>
    <lastName>Doe</lastName>
    <dob>1986-02-14 03:46:16.381 UTC</dob>
</customer>

我们可以通过创建别名来隐藏此 XML。

3.1.类别名

我们以编程方式或使用注释向 XStream 实例注册别名。我们可以使用 @XStreamAlias 注释我们的 Customer 类:

@XStreamAlias("customer")
public class Customer {
    //...
}

现在我们需要配置 XStream 实例以使用此注释:

xstream.processAnnotations(Customer.class);

或者,如果我们希望以编程方式配置别名,我们可以使用下面的代码:

xstream.alias("customer", Customer.class);

3.2.字段别名

假设我们有以下 XML:

<customer>
    <fn>John</fn>
    <lastName>Doe</lastName>
    <dob>1986-02-14 03:46:16.381 UTC</dob>
</customer>

fn 标记与 Customer 对象中的任何字段都不匹配,因此如果我们希望反序列化它,我们需要为该字段定义一个别名。我们可以使用以下注释来实现这一点:

@XStreamAlias("fn")
private String firstName;

或者,我们可以通过编程实现相同的目标:

xstream.aliasField("fn", Customer.class, "firstName");

4. 隐式集合

假设我们有以下 XML,其中包含 ContactDetails 的简单列表:

<customer>
    <firstName>John</firstName>
    <lastName>Doe</lastName>
    <dob>1986-02-14 04:14:20.541 UTC</dob>
    <ContactDetails>
        <mobile>6673543265</mobile>
        <landline>0124-2460311</landline>
    </ContactDetails>
    <ContactDetails>...</ContactDetails>
</customer>

我们想要将 ContactDetails 列表加载到 List 中我们的 Java 对象中的字段。我们可以通过使用以下注释来实现这一点:

@XStreamImplicit
private List<ContactDetails> contactDetailsList;

或者,我们可以通过编程实现相同的目标:

xstream.addImplicitCollection(Customer.class, "contactDetailsList");

5. 忽略字段

假设我们有以下 XML:

<customer>
    <firstName>John</firstName>
    <lastName>Doe</lastName>
    <dob>1986-02-14 04:14:20.541 UTC</dob>
    <fullName>John Doe</fullName>
</customer>

在上面的 XML 中,我们有额外的元素我们的 Java Customer 对象缺少它。

如果我们尝试反序列化上面的 xml 而不关心额外的元素,程序会抛出 UnknownFieldException

No such field com.baeldung.pojo.Customer.fullName

正如异常明确指出的那样,XStream 无法识别字段 fullName

为了解决这个问题,我们需要将其配置为忽略未知元素:

xstream.ignoreUnknownElements();

6. 属性字段

假设我们有一个 XML,其属性作为元素的一部分,我们希望将其反序列化为对象中的字段。我们将向 ContactDetails 对象添加 contactType 属性:

<ContactDetails contactType="Office">
    <mobile>6673543265</mobile>
    <landline>0124-2460311</landline>
</ContactDetails>

如果我们想要反序列化 contactType XML 属性,我们可以在我们希望它出现的字段上使用 @XStreamAsAttribute 注释:

@XStreamAsAttribute
private String contactType;

或者,我们可以通过编程实现相同的目标:

xstream.useAttributeFor(ContactDetails.class, "contactType");

七、结论

在本文中,我们探讨了使用 XStream 将 XML 反序列化为 Java 对象时可用的选项。

可以从链接的GitHub 存储库下载本文的完整源代码。