Serializing Java Objects with XStream
Joe Walnes's XStream is a unique open-source Java library for serializing objects into XML and deserializing that XML into objects. Unlike other APIs, such as David Megginson's XMLWriter or Elliotte Rusty Harold's XOM, which use specific classes and methods to produce XML, XStream relies on Java idioms such as object names to produce element names and strings within classes to produce element content. It also produces a kind of reflection of objects in XML.
XStream is being actively developed by a small project team with over a dozen contributors. It promises to become a very useful tool for persistence and transport; and I think it embraces, as does Joe Walnes, some virtues of agile programming.
Joe Walnes explained the following in private correspondence:
XStream's primary purpose is for serialization. It allows existing Java objects to be converted to clean XML and then restored again, without modifications. This is particularly useful as a form of persistence (no complicated database mappings required) or for sending objects over the wire. It has been optimized for this and is in heavy use on production systems.
XStream offers a two-minute tutorial and JavaDocs. Unfortunately, the XStream distribution doesn't yet provide example programs, though there is a test suite. This article demonstrates several example Java programs that should help you get started with XStream today.
The current, stable version of XStream is
1.0.1, which was released at the end of May 2004. This article,
however, uses the latest
snapshot available in late July 2004. Programs were compiled and
run with Sun's Java 1.4.2_05 and included an XStream JAR
(xstream-SNAPSHOT.jar) in the classpath at compile
time. The examples also use Aleksander Slominski's speedy XML Pull Parser or XPP (xpp3-1.1.3.3_min.jar) at runtime. Both
the stable and snapshot versions of XStream includes JARs. Download
both the XStream archive and the example programs to a working
directory.
A Simple Program
Let's start with a simple program that shows the basics of XStream
serialization. The program Hello.java follows. It is
available in the sample archive for this article. The program uses XStream to output a
string in XML:
import com.thoughtworks.xstream.XStream;
public class Hello {
public static void main(String[] args) {
XStream xstream = new XStream();
String salutation = "Hello, World!";
String xml = xstream.toXML(salutation);
System.out.print(xml);
}
}
The public class Hello imports only one class,
com.thoughtworks.xstream.XStream. It calls a
constructor for XStream, creating the object xstream.
Then it uses the toXML method to store the
string salutation as XML, and writes the XML to the
console using the System.out.print method.
Compile the program using this command line at a shell prompt in the working directory:
javac -classpath .;xstream-SNAPSHOT.jar Hello.java
This shows the current directory and the XStream JAR in the
classpath explicitly. (Of course, use colons instead of semicolons if
you are on Unix.) Once Hello.java compiles successfully,
run it with this line:
java -cp .;xstream-SNAPSHOT.jar;xpp3-1.1.3.3_min.jar Hello
This line adds the XPP JAR to the command line; it should output the following:
<string>Hello, World!</string>
XStream automatically wraps the Java String salutation
in the XML element string. The string
element appears to be an example of XStream's style of XML reflection.
If you really want to see this in action,
try Reflect.java:
import com.thoughtworks.xstream.XStream;
public class Reflect {
public static void main(String[] args) {
XStream xstream = new XStream();
String xml = xstream.toXML(xstream);
System.out.print(xml);
}
}
This program serializes the object xstream into XML,
producing over 7,000 lines of "reflection." If you want to avoid the
dependency on XPP, you can use DOM instead, like this
(HelloDom.java):
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
public class HelloDom {
public static void main(String[] args) {
XStream xstream = new XStream(new DomDriver());
String salutation = "Hello, World!";
String xml = xstream.toXML(salutation);
System.out.print(xml);
}
}
The differences between Hello.java and
HelloDom.java are highlighted in
bold: HelloDom.java imports the additional
class com.thoughtworks.xstream.io.xml.DomDriver and then
uses DomDriver in the XStream constructor. When you
run HelloDom, you can drop the reference to the XPP JAR
on your classpath.
Using Another Class
The next program, Instant.java, uses a non-public outer
class, Date, to represent some data for a date:
import com.thoughtworks.xstream.XStream;
class Date {
int year;
int month;
int day;
}
public class Instant {
public static void main(String[] args) {
XStream xstream = new XStream();
Date date = new Date();
date.year = 2004;
date.month = 8;
date.day = 15;
xstream.alias("date", Date.class);
String decl = "\n";
String xml = xstream.toXML(date);
System.out.print(decl + xml);
}
}
The class Date holds three fields, all of which are
integers. After the Date constructor, each of these
fields is given a value, e.g. date.year =
2004;. The alias method creates an alias XML
element name for the Date class, changing the default
name from Date to date. XStream uses the
fully qualified class name for the element name, including the package
name, so the alias method will come in handy for tweaking
names. The program also creates an XML declaration and uses it in its
output.
Compile and run the program, and you will get this output:
<xml version="1.0"?>
<date>
<year>2004<year>
<month>8<month>
<day>15<day>
<date>
Deserializing XML to Objects
The final program, Deserialize.java, shows you how to
deserialize XML to an object, and then to reuse it:
import com.thoughtworks.xstream.XStream;
class Date {
int year = 2004;
int month = 8;
int day = 15;
}
public class Deserialize {
public static void main(String[] args) {
XStream xstream = new XStream();
Date date = new Date();
xstream.alias("date", Date.class);
String xml = xstream.toXML(date);
System.out.print(xml);
Date newdate = (Date)xstream.fromXML(xml);
newdate.month = 12;
newdate.day = 2;
String newxml = xstream.toXML(newdate);
System.out.print("\n\n" + newxml);
}
}
Note this line from Deserialize.java:
Date newdate = (Date)xstream.fromXML(xml);
The line creates a new object newdate using the
fromXML method to convert the string xml
back to an object (also casting it as Date).
After compiling and running Deserialize.java,
you will see this output (two XML documents):
<date>
<year>2004<year>
<month>8<month>
<day>15<day>
<date>
<date>
<year>2004<year>
<month>12<month>
<day>2<day>
<date>
The second instance of date comes from the object
created from deserialized XML.
Conclusion
This article has introduced you to the basic features and capabilities of XStream. For additional insights, you might have a look at XStream test programs that use maps or collections (from the test suite). There is plenty of CVS activity, enough to give me hope that XStream is in active development and will be around for awhile. I think XStream takes a nifty approach to XML serialization and persistence, and I'll be keeping my eye on it for even more innovation in the future.
- Serializing Java Objects with XStream
2009-03-05 22:56:22 charlesarun - Desirialize example correction
2007-05-25 06:57:47 waikar - Handling of null values with XStream
2005-01-11 00:51:57 anuj7700 - Handling of null values with XStream
2008-11-16 06:47:35 Dimpleg - Handling of null values with XStream
2005-02-24 21:39:29 sj5104 - Handling of null values with XStream
2007-11-02 09:51:01 martynwilson