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 可以通过多种方式输入,包括 File 、 InputStream 、 Reader 或 String 。为简单起见,我们假设上面的 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 存储库下载本文的完整源代码。