Reputation: 4285
This is the scenario:
<family>
<person>name</person>
<person>
<address> street </adress>
<address> street </address>
</person>
</family>
The person value can be a list of addresses or just the person name. I think the solution is to use a converter but how do you do that?
Example class : (do note that this is for illustration)
public class Person {
private String name;
private List<Address> address;
}
public class Address {
private String street;
}
Upvotes: 1
Views: 528
Reputation: 14212
You do need to use a converter. Here is the converter for your example:
public class PersonConverter implements Converter {
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
Person person = (Person) value;
if(person.name != null){
writer.setValue(person.name);
} else if(person.address != null){
for (Address address : person.address){
writer.startNode("address");
writer.setValue(address.street);
writer.endNode();
}
}
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
Person person = new Person();
person.name = reader.getValue();
if(person.name.trim().length()==0){
person.name = null;
}
List<Address> addresses = getAddress(reader, new ArrayList<Address>());
person.address = addresses;
if(person.address.size() == 0){
person.address = null;
}
return person;
}
private List<Address> getAddress(HierarchicalStreamReader reader, List<Address> addresses){
if (!reader.hasMoreChildren()){
return addresses;
}
reader.moveDown();
if(reader.getNodeName().equals("address")){
addresses.add(new Address(reader.getValue()));
reader.moveUp();
getAddress(reader, addresses);
}
return addresses;
}
public boolean canConvert(Class clazz) {
return clazz.equals(Person.class);
}
}
Here is the main method:
public static void main(String[] args) {
List<Person> persons = new ArrayList<Person>();
persons.add(new Person("John"));
List<Address> adds = new ArrayList<Address>();
adds.add(new Address("123 street"));
adds.add(new Address("456 street"));
persons.add(new Person(adds));
Family family = new Family(persons);
XStream stream = new XStream();
stream.registerConverter(new PersonConverter());
stream.processAnnotations(new Class[]{Family.class});
String xml = stream.toXML(family);
System.out.println(xml);
Family testFam = (Family) stream.fromXML(xml);
System.out.println("family.equals(testFam) => "+family.equals(testFam));
}
If you implement the equals method for the Family
, Person
, and Address
classes it should print that they are equal at the end of the method when ran. Also worth noting is that I used some Annotations on the Family
. I used @XStreamAlias("family")
on the Class itself, and then on the collection of Person
objects I used @XStreamImplicit(itemFieldName="person")
.
And here is my ouput when I run the main method supplied:
<family>
<person>John</person>
<person>
<address>123 street</address>
<address>456 street</address>
</person>
</family>
family.equals(testFam) => true
Upvotes: 2