How to serialize and deserialize Java Object to XML using Xstream
18877
Mar 20, 2016
Many times we need to convert a Java object to XML string or xml string to object, in that case Xstream is good choice specially if we are working with third party Java classes where we don't have source of class to change.
If a Java object that needs to be converted to XML string, and the code is not available to modify, then we have only few options to choose a tool which can convert object to xml string. Basically in this case we need to provide some metadata (e.g. mappings to class property to xml element name, also sometimes called bindings) to the converter. This meta data can be an external xml file or can be programmatically. Using Xstream we can provide these metadata programmatically.
Lets take some examples. Suppose we have two classed (could be third party) as below
Country.java
package com.groupkt.xstream;
import java.util.List;
public class Country { private String name; private String isoCode; private String currency; private List states; /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the isoCode */ public String getIsoCode() { return isoCode; } /** * @param isoCode the isoCode to set */ public void setIsoCode(String isoCode) { this.isoCode = isoCode; } /** * @return the currency */ public String getCurrency() { return currency; } /** * @param currency the currency to set */ public void setCurrency(String currency) { this.currency = currency; } /** * @return the states */ public List getStates() { return states; } /** * @param states the states to set */ public void setStates(List states) { this.states = states; }
@Override public String toString() { return new StringBuilder() .append("name:").append(name) .append(",isoCode:").append(isoCode) .append(",currency:").append(currency) .append(",states:").append(states) .toString(); } }
State.java
package com.groupkt.xstream;
public class State { private String name; private String capital;
public State(String name, String capital) { this.name = name; this.capital = capital; } /** * @return the name */ public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** * @return the capital */ public String getCapital() { return capital; } /** * @param capital the capital to set */ public void setCapital(String capital) { this.capital = capital; }
@Override public String toString() { return new StringBuilder() .append("name:").append(name) .append("capital:").append(capital) .toString(); } }
and want a xml string from an Country object similar to
private static XStream getXstreamObject() { XStream xstream = new XStream(); // DomDriver and StaxDriver instances also can be used with constructor return xstream; }
this method will return an Xstream object which will convert Country object to xml string. lets create a test class to test it
public static void main(String[] args) { Country country = new Country(); country.setName("India"); country.setIsoCode("IND"); country.setCurrency("INR"); List<State> states = new ArrayList<State>(); states.add(new State("Uttar Pradesh", "Lucknow")); states.add(new State("Maharashtra", "Mumbai")); country.setStates(states);
private static XStream getXstreamObject() { XStream xstream = new XStream(); // DomDriver and StaxDriver instances also can be used with constructor return xstream; } }
and this will convert the country object similar to
Step 3. Configure the Xstream programmatically to get desired xml
now we need to tweak the Xstream to get the desired xml. change the getXstreamObject() method as below
private static XStream getXstreamObject() { XStream xstream = new XStream(); // DomDriver and StaxDriver instances also can be used with constructor xstream.alias("country", Country.class); // this will remove the Country class package name xstream.alias("state", State.class); // this will remove the State class package name xstream.useAttributeFor(Country.class, "isoCode"); // make the isoCode to attribute from element xstream.aliasField("code", Country.class, "isoCode"); // change 'isoCode' to code xstream.addImplicitCollection(Country.class, "states"); // don't want all states inside . return xstream; }