Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In a previous article, we learned how to use XStream to serialize Java objects to XML. In this tutorial, we will learn how to do the reverse: deserialize XML to Java objects. These tasks can be accomplished using annotations or programmatically.

To learn about the basic requirements for setting up XStream and its dependencies, please reference the previous article.

2. Deserialize an Object from XML

To start with, suppose we have the following 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>

We need to convert this to a Java Customer object:

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

The XML can be input in a number of ways, including File, InputStream, Reader, or String. For simplicity, we’ll assume that we have the XML above in a String object.

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

3. Security Aspects

Because XStream uses undocumented Java features as well as Java Reflection, it may be vulnerable to an Arbitrary Code Execution or Remote Command Execution attacks.

In-depth security considerations are out of the scope of this tutorial, but we do have a dedicated article that explains the threat. Also, it’s worth checking out XStream’s official page.

For the purpose of our tutorial, let’s assume that all our classes are “safe”. Consequently, we need to configure XStream:

XStream xstream = new XStream();
xstream.allowTypesByWildcard(new String[]{"com.baeldung.**"});

4. Aliases

In the first example, the XML had the fully-qualified name of the class in the outermost XML tag, matching the location of our Customer class. With this setup, XStream easily converts the XML to our object without any extra configuration. But we may not always have these conditions. We might not have control over the XML tag naming, or we might decide to add aliases for fields.

For example, suppose we modified our XML to not use the fully-qualified class name for the outer tag:

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

We can covert this XML by creating aliases.

4.1. Class Aliases

We register aliases with the XStream instance either programmatically or using annotations. We can annotate our Customer class with @XStreamAlias:

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

Now we need to configure our XStream instance to use this annotation:

xstream.processAnnotations(Customer.class);

Alternatively, if we wish to configure an alias programmatically, we can use the code below:

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

4.2. Field Aliases

Suppose we have the following XML:

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

The fn tag doesn’t match any fields in our Customer object, so we will need to define an alias for that field if we wish to deserialize it. We can achieve this using the following annotation:

@XStreamAlias("fn")
private String firstName;

Alternatively, we can accomplish the same goal programmatically:

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

5. Implicit Collections

Let’s say we have the following XML, containing a simple list of 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>

We want to load the list of ContactDetails into a List<ContactDetails> field in our Java object. We can achieve this by using the following annotation:

@XStreamImplicit
private List<ContactDetails> contactDetailsList;

Alternatively, we can accomplish the same goal programmatically:

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

6. Ignore Fields

Let’s say we have following XML:

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

In the XML above, we have extra element <fullName> which is missing from our Java Customer object.

If we try to deserialize the above xml without taking any care for extra element, program throws an UnknownFieldException.

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

As the exception clearly states, XStream does not recognize the field fullName.

To overcome this problem we need to configure it to ignore unknown elements:

xstream.ignoreUnknownElements();

7. Attribute Fields

Suppose we have XML with attributes as part of elements that we’d like to deserialize as a field in our object. We will add a contactType attribute to our ContactDetails object:

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

If we want to deserialize the contactType XML attribute, we can use the @XStreamAsAttribute annotation on the field we’d like it to appear in:

@XStreamAsAttribute
private String contactType;

Alternatively, we can accomplish the same goal programmatically:

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

8. Conclusion

In this article, we explored the options we have available when deserializing XML to Java objects using XStream.

The complete source code for this article can be downloaded from the linked GitHub repository.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.