I was just getting the following output from XStream when trying to serialize an object which has a collection property:
<addresses class="java.util.Arrays$ArrayList">
<a class="address-array">
<address>
It had to step through the code to see what was going on.
The key is in the subtlety of the type of the list that I was putting in there. Notice that actually its not an java.util.ArrayList
its actually an inner class of the Arrays
, called, happily $ArrayList
, so I had been staring at it the whole time and not noticed.
When XStream serializes its doing the following:
Class actualType = newObj.getClass();
Class defaultType = mapper.defaultImplementationOf(fieldType);
if (!actualType.equals(defaultType)) {
String serializedClassName = mapper.serializedClass(actualType);
if (!serializedClassName.equals(mapper.serializedClass(defaultType))) {
String attributeName = mapper.aliasForSystemAttribute(“class”);
if (attributeName != null) {
writer.addAttribute(attributeName, serializedClassName);
}
}
}
From version 1.3.1 – AbstractReflectionConverter:127
So its asking the mapper what the default implementation of the type is. The type in this case was java.util.List
and the default implementation is of course java.util.ArrayList
. It is not seeing java.util.Arrays$ArrayList
as the same thing and so thinks it needs to specify it.
Now you might be asking, how come I have a strange inner class version of ArrayList
? Well the thing is, I thought I was being clever in the set up of my test data and im using:
addresses = Arrays.asList(
new AddressBuilder().addressType(“home”).streetAddress(“1 The street”).build(),
new AddressBuilder().addressType(“work”).streetAddress(“2 The street”).build(),
new AddressBuilder().addressType(“holiday”).streetAddress(“3 The street”).build()
);
To set up my test data. asList
does this:
public static List asList(T… a) {
return new ArrayList(a);
}
private static class ArrayList extends AbstractList
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private Object[] a;
Where it uses its own implementation of ArrayList.
Phew, another fun couple of hours spent there.