Suppose I want to store many small configuration objects in XML, and I don't care too much about the format. The XMLDecoder class built into the JDK would work, and from what I hear, XStream works in a similar way.
What are the advantages to each library?
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.
For most use cases, the XStream instance is thread-safe, once configured (there are caveats when using annotations) Clear messages are provided during exception handling to help diagnose issues. Starting with version 1.4.
Another suggestion: consider using JAXB (http://jaxb.dev.java.net). If you are using JDK 1.6, it comes bundled, check out "javax.xml.bind" for details, so no need for additional external jars.
JAXB is rather fast. I like XStream too, but it's bit slower. Also, XMLEncoder is bit of a toy (compared to other options)... but if it works, there's no harm in using it.
Also: one benefit of JAXB is that you can also bind partial document (sub-trees) with it; no need to create object(s) for the whole file. For this you need to use Stax (XMLStreamReader) to point to root element of the sub-tree, then bind. No need to use SAX, even for most large files, as long as it can be processed chunk by chunk.
I really like the XStream library. It does a really good job of outputting fairly simple xml as a result of a provided Java object. It works great for reproducing the object back from the xml as well. And, one of our 3rd party libraries already depended on it anyway.
We chose to use it because we wanted our xml to be human readable. Using the alias function makes it much nicer.
You can extend the library if you want some portion of an object to deserialize in a nicer fashion. We did this in one case so the file would have a set of degrees, minutes, and seconds for a latitude and longitude, instead of two doubles.
The two minute tutorial sums up the basic usage, but in the interest of keeping the information in one spot, I'll try to sum it up here, just a little shorter.
// define your classes
public class Person {
private String firstname;
private PhoneNumber phone;
// ... constructors and methods
}
public class PhoneNumber {
private int code;
private String number;
// ... constructors and methods
}
Then use the library for write out the xml.
// initial the libray
XStream xstream = new XStream();
xstream.alias("person", Person.class); // elementName, Class
xstream.alias("phone", PhoneNumber.class);
// make your objects
Person joe = new Person("Joe");
joe.setPhone(new PhoneNumber(123, "1234-456"));
// convert xml
String xml = xstream.toXML(joe);
You output will look like this:
<person>
<firstname>Joe</firstname>
<phone>
<code>123</code>
<number>1234-456</number>
</phone>
</person>
To go back:
Person newJoe = (Person)xstream.fromXML(xml);
The XMLEncoder is provided for Java bean serialization. The last time I used it, the file looked fairly nasty. If really don't care what the file looks like, it could work for you and you get to avoid a 3rd party dependency, which is also nice. I'd expect the possibility of making the serialization prettier would be more a challenge with the XMLEncoder as well.
XStream outputs the full class name if you don't alias the name. If the Person class above had
package example;
the xml would have "example.Person" instead of just "person".
If you are planning on storing all those configuration objects in a single file, and that file will be quite large, both the options you've outlined above could be quite memory intensive, as they both require the entire file to be read into memory to be deserialized.
If memory usage is a concern (the file containing the XML will be very large), I recommend SAX.
If memory usage is not a concern (the file containing the XML will not be very large), I'd use whatever is included with the default JRE (in this case XMLDecoder) just to remove 3rd party dependencies.
I'd also prefer XStream as it is really easy to use and to extend. You can quickly start if you're going with the default setup. If you need to customize the behavior it has a very clean API and a lot of extension points, so you have really fine grained control over the things you want to tweak without interfering with other parts of the marshalling process.
As the XML that is created by XStream looks nice, manual editing is also simple. If the output doesn't fulfill your needs and the long list of available Converters doesn't contain the one you need, it's fairly simple to write your own.
A big plus is also the good documentation on their homepage.
I always find XStream very tempting, because it's so easy to get going. However, invariably I end up replacing it. It's really quite buggy, and its collection handling could use a lot of work.
As a result, I usually switch to JAXB. It's an awful lot more robust, it's pretty much bug-free, and a more flexible than XStream.
Addition to @jay answer with example:
Code:
PortfolioAlternateIdentifier identifier = new PortfolioAlternateIdentifier();
identifier.setEffectiveDate(new Date());
identifier.setSchemeCode("AAA");
identifier.setIdentifier("123456");
The output using XStream:
<PortfolioAlternateIdentifier>
<effectiveDate>2014-05-02 20:14:15.961 IST</effectiveDate>
<schemeCode>AAA</schemeCode>
<identifier>123456</identifier>
</PortfolioAlternateIdentifier>
The output using XMLEncoder:
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0_38" class="java.beans.XMLDecoder">
<object class="PortfolioAlternateIdentifier">
<void property="effectiveDate">
<object class="java.util.Date">
<long>1399041855961</long>
</object>
</void>
<void property="identifier">
<string>123456</string>
</void>
<void property="schemeCode">
<string>AAA</string>
</void>
</object>
</java>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With