I am using XStream to convert XML into domain objects, and have come by a problem. Omitting a few details, the XML looks like this :
<airport>
<flights>
<flight>.....</flight>
<flight>.....</flight>
<flight>.....</flight>
</flights>
</airport>
There can be 0 to N flight
elements. The flight elements themselves contain other elements. I have created classes for airport, flights, and flight and registered them with the xstream.alias function.
xstream = new XStream();
xstream.alias("airport", AirportPojo.class);
xstream.alias("flights", FlightsPojo.class);
xstream.alias("flight", FlightPojo.class);
xstream.useAttributeFor(AirportPojo.class, "flights");
xstream.addImplicitCollection(FlightsPojo.class, "flights", FlightPojo.class);
AirportPojo airportPojo = (AirportPojo) xstream.fromXML(xml);
So, after converting, this gives me an AirportPojo object containing a FlightsPojo object, containing a collection of FlightPojo objects. However, when there are 0 flight elements it seems that the collection of FlightPojos is null
. I would expect (and prefer) the list to be initialized but with zero elements in it. How could I accomplish this? Bear in mind that I cannot use annotations as this is a legacy project.
How about implementing a custom converter?
class FlightsConverter implements Converter {
@Override
public boolean canConvert(Class clazz) {
return clazz.equals(FlightsPojo.class);
}
@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
FlightsPojo flightsPojo = new FlightsPojo();
flightsPojo.setFlights(new ArrayList<FlightPojo>());
while (reader.hasMoreChildren()) {
reader.moveDown();
FlightPojo flightPojo = (FlightPojo) context.convertAnother(flightsPojo, FlightPojo.class);
flightsPojo.getFlights().add(flightPojo);
System.out.println(reader.getValue());
reader.moveUp();
}
return flightsPojo;
}
@Override
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
// todo...
}
}
And hook it in like so:
XStream xstream = new XStream();
xstream.registerConverter(new FlightsConverter());
xstream.alias("airport", AirportPojo.class);
xstream.alias("flights", FlightsPojo.class);
xstream.alias("flight", FlightPojo.class);
xstream.useAttributeFor(AirportPojo.class, "flights");
AirportPojo airportPojo = (AirportPojo) xstream.fromXML(xml);
Hope this helps ;)