XStream

SerializationJavaXMLJSONObject MappingReflectionLightweight Library

Library

XStream

Overview

XStream is a lightweight and easy-to-use library for converting Java objects to and from XML. Using reflection to automatically analyze object graphs, it can serialize most objects without mapping definitions. Beyond XML, it supports JSON format and is widely used for configuration file processing, web service data exchange, and object persistence.

Details

XStream 1.4.20 is a mature library with over 10 years of development history. As of 2025, it is actively maintained and provides high reliability for Java object to XML conversion. It can serialize most objects without annotations and can handle private and final fields. Enhanced security features ensure safe processing through type control during deserialization.

Key Features

  • Reflection-based: Automatically analyzes object structure without mapping definitions
  • No annotations required: Can serialize most objects by default
  • Multiple output formats: Supports XML, JSON, and other formats
  • Customizability: Custom conversion logic through converters
  • Security features: Safe processing through type control during deserialization
  • Thread-safe: XStream instances are thread-safe after configuration

Pros and Cons

Pros

  • Very low learning curve, basic conversion possible with just a few lines of code
  • No mapping definitions required, existing Java classes can be used as-is
  • Serializes complete object graphs including private and final fields
  • Human-readable XML makes debugging and testing easy
  • Flexible customization of element and attribute names through aliasing
  • JUnit-friendly and ideal for unit testing

Cons

  • Larger size compared to binary formats due to XML-based nature
  • Performance may be inferior to modern libraries like Jackson
  • Poor compatibility with obfuscation due to reflection usage
  • Other libraries recommended when primarily dealing with JSON
  • Security vulnerabilities risk without proper security configuration
  • Memory usage may increase with large object graphs

Reference Pages

Code Examples

Basic Setup

<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.20</version>
</dependency>

Basic Usage

import com.thoughtworks.xstream.XStream;

// Create XStream instance
XStream xstream = new XStream();

// Security configuration (required)
xstream.allowTypesByWildcard(new String[] {
    "com.example.myapp.**"
});

// Person class example
public class Person {
    private String name;
    private int age;
    private Address address;
    
    // Constructors, getters, setters omitted
}

// Object to XML
Person person = new Person("John Doe", 30);
String xml = xstream.toXML(person);
System.out.println(xml);

// XML to Object
Person restored = (Person) xstream.fromXML(xml);

Alias Configuration

// Class name aliases
xstream.alias("person", Person.class);
xstream.alias("address", Address.class);

// Field name aliases
xstream.aliasField("full-name", Person.class, "name");
xstream.aliasField("years", Person.class, "age");

// Output as attributes
xstream.useAttributeFor(Person.class, "age");
xstream.aliasAttribute(Person.class, "age", "years");

Creating Custom Converter

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class DateConverter implements Converter {
    private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
    
    public boolean canConvert(Class type) {
        return type.equals(Date.class);
    }
    
    public void marshal(Object source, HierarchicalStreamWriter writer,
                       MarshallingContext context) {
        Date date = (Date) source;
        writer.setValue(formatter.format(date));
    }
    
    public Object unmarshal(HierarchicalStreamReader reader,
                           UnmarshallingContext context) {
        try {
            return formatter.parse(reader.getValue());
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}

// Register converter
xstream.registerConverter(new DateConverter());

JSON Format Output

import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;

// Create XStream for JSON
XStream xstream = new XStream(new JsonHierarchicalStreamDriver());

// Convert object to JSON
Person person = new Person("Jane Smith", 25);
String json = xstream.toXML(person);
System.out.println(json);

// Convert JSON to object
Person restored = (Person) xstream.fromXML(json);

Collection Processing

// Serialize list
List<Person> people = Arrays.asList(
    new Person("John Doe", 30),
    new Person("Jane Smith", 25)
);

xstream.alias("people", List.class);
xstream.alias("person", Person.class);
xstream.addImplicitCollection(List.class, "list");

String xml = xstream.toXML(people);

Detailed Security Configuration

// Security-focused configuration
XStream xstream = new XStream();

// Explicitly specify allowed types
xstream.allowTypes(new Class[] {
    Person.class,
    Address.class,
    Date.class
});

// Allow by package
xstream.allowTypesByWildcard(new String[] {
    "com.example.myapp.model.**",
    "java.util.**",
    "java.lang.**"
});

// Deny specific types
xstream.denyTypes(new Class[] {
    java.beans.EventHandler.class
});