Indeed, for this you will need a custom converter, since these are two nested collections that you do not want to show, and these objects may have other children that will be serialized.
This is a case that does not apply directly to XStream, but is easily fixed using a custom converter.
You can find all this in the git clone of your project , which contains all these changes. But since everything should be visible here, I will subsequently explain the key parts of the question, including some code examples.
I implemented such a converter for your project. The code that performs the conversion is this:
@Override public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { TestRow test = (TestRow)source; for (TestArguments arg : test.getArguments()) { for (ArgObject val : arg.getAllTestArguments()) { writer.startNode(val.getKey()); writer.addAttribute("type", val.getType()); writer.setValue(val.getVal()); writer.endNode(); } } } @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { TestArguments testargs = new TestArguments(); while (reader.hasMoreChildren()) { reader.moveDown(); String typeval = reader.getAttribute("type"); if (typeval.isEmpty()) { typeval = "null"; } testargs.getAllTestArguments().add(new ArgObject(reader.getNodeName(), typeval, reader.getValue())); reader.moveUp(); } TestRow result = new TestRow(testargs); return result; }
This will serialize all ArgObjects to xml with the flat node structure you define in ArgConverter . From deserialization, an object is created back from this data.
You had two errors in the source code that prevented deserialization:
- Xerit deserialization does not recognize all Annotations aliases. This had problems with your root
SuiteData element (with an alias). To do this, I added an alias to an XStream object like this xStream.alias("suite", SuiteData.class); in your XMLDataHelper . - If you create an instance of
TestArguments with a default constructor (as you have to do with deserialization), you call reset, which sets the argsWrapper member to null, which then makes adding arguments completely impossible. I fixed this to initialize this member variable in the reset method ( argsWrapper = new ArrayList<ArgObject>(); ).
As far as I understand your code, this works as expected for serialization / deserialization. I wrote a small test program to force this process in different ways, and it seems to give the same result:
public class XMLDataHelperTest { public static void main(String[] args) { File file = new File(System.getProperty("user.dir"), "test.xml"); if (file.isFile()) { assertTrue(file.delete()); }
Matthias
source share