Java XStream – Complex Example
Today we will tell you more about java XStream. If you are looking for basics of java XStream please refer to our earlier tutorial – Java Xstream.
Here is our more advanced code snippet.
ComplexExample.java
package com.itcuties.java.xstream.data; import java.io.ObjectStreamException; import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamImplicit; /** * More complex example. It is a summary of already showed issues. It also shows * several additional things: <li>transient field modifier will cause the field * NOT to be loaded even if annotated and present in xml <li>constructor is not * being invoked <li>default values given to fields will be replaced if the * fields are present in xml file <li>how to force xstream to set a default * value for an attribute if it is not present in xml * * @author itcuties * */ @XStreamAlias("complex-example") public class ComplexExample { @XStreamAlias("number-1") private int number1 = 9;// default value will be replaced if present in the xml @XStreamAlias("number-2") private int number2 = 12;// default value will be erased if NOT present in xml (in this case it will be set to 0) @XStreamAlias("number-3") private Short number3;// any numeric type will do (Object or primitive) just make sure the number value will fit @XStreamAlias("attribute") @XStreamAsAttribute private String attribute; @XStreamAlias("default-attribute") @XStreamAsAttribute private String defaultAttribute; @XStreamAlias("transientString") private transient String transientString;// this will not be read because it // is transient @XStreamImplicit(itemFieldName = "data") private List<String> data; @XStreamAlias("book") private Book book; // you can use other classes that were annotated // (just give the top most class to xstream for // annotation processing, // it will find all others that are used) public ComplexExample() { System.out.println("Very talkative constructor."); } @Override public String toString() { return "ComplexExample [number1=" + number1 + ", number2=" + number2 + ", number3=" + number3 + ", attribute=" + attribute + ", defaultAttribute=" + defaultAttribute + ", transientString=" + transientString + ", data=" + data + ", book=" + book + "]"; } /** * There is one major flaw in XStream. Unfortunately it has no way of * telling if a field or attribute should get any default value if not * present in the xml file. Because constructor is not being invoked we * cannot set the value there. Neither setting the value in field definition * will work. The resulting instance will always have zero or null values in * the fields. * * The only way of setting the desired default value is using the following * method. It is called during deserialization process and here we can check * if the field value is null. If yes it means that it's tag is not present * and we can set the default value if needed. * * @return this * @throws ObjectStreamException */ private/* or public or protected or none */Object readResolve() throws ObjectStreamException { if (defaultAttribute == null) { defaultAttribute = "DEFAULT ATTRIBUTE VALUE"; } return this; } }
complex-example.xml
<complex-example attribute="some attribute"> <number-1>1</number-1> <number-3>3</number-3> <transientString> Some transient string that will not be loaded. </transientString> <data>A</data> <data>B</data> <data>C</data> <data>D</data> <data>E</data> <book> <title>The Lord of The Rings</title> <author>J.R.R. Tolkien</author> <pages-count>1024</pages-count> </book> </complex-example>
To read java object from xml call the fromXML
method of the XStream
class. Here is the example.
XStream xStream = new XStream(); xStream.processAnnotations(ComplexExample.class); Object readObject = xStream.fromXML(new File("xmls/complex-example.xml")); System.out.println("Object loaded by xstream: " + readObject);
When you will run this example you’ll get the following output.
Object loaded by xstream: ComplexExample [number1=1, number2=0, number3=3, attribute=some attribute, defaultAttribute=DEFAULT ATTRIBUTE VALUE, transientString=null, data=[A, B, C, D, E], book=Book [title=The Lord of The Rings, author=J.R.R. Tolkien, pagesCount=1024, fieldThatIsNotInTheXml=null]]
Code summary
There are some things to remember here and they are as follow…
transient keyword
When you use a transient
keyword for a class attribute it’s value will not be read from the XML file although it is present there.
Default constructor
Class default constructor is not called to create the object while reading it from XML file.
Default values
If you want to set class default values which are different from the default java types values ( 0
for int
, false
for boolean
etc.) you need to assign them manually in the readResolve()
method.
Using annotated classes
You can use other classes that were annotated, just give the top most class to xstream for annotation processing it will find all others that are used.
Download this sample code here.
This code is available on our GitHub repository as well.
Hi… You saved me with this brilliant tutorial, Im struggling from one day to solve an issue in a Complex XML as you shown in this example… It really helped to solve the issue. Thank you so much for your valuable tutorial…..