Zenohao
Zenohao

Reputation: 23

Cannot construct java.util.Collection xstream

I am having troubles unmarshalling some xml using the XStream library. The related java class uses the java.util.Collection class in order to store some attributes, which I understand is a problem for XStream. However, I am unable to change the Java class to use something like ArrayList due to various reasons. Is there a way to unmarshal the xml using XStream, or should I search other libraries for a solution?

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import org.testng.annotations.Test;

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class ControllerTest {

    @XStreamAlias("controllers")
    public class ControllerList implements Serializable {
        @XStreamImplicit(
                itemFieldName = "controller"
        )
        private List<Controller> controllers = new ArrayList();

        public ControllerList() {
        }

        public List<Controller> getControllers() {
            return this.controllers;
        }

        public void setControllers(List<Controller> controllers) {
            this.controllers = controllers;
        }
    }

    @XStreamAlias("controller")
    public class Controller extends BasicInfo {
        @XStreamImplicit(
                itemFieldName = "storageInfo"
        )
        private Collection<BasicInfo> storage;

        public Controller() {
        }

        public Collection<BasicInfo> getStorage() {
            return this.storage;
        }

        public void setStorage(Collection<BasicInfo> storage) {
            this.storage = storage;
        }
    }

    @XStreamAlias("basicinfo")
    public class BasicInfo{
        private String name;

        public BasicInfo() {
        }

        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    @Test(groups = {"edge"})
    public void testControllers() {
        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><controllers><controller><storageInfo>" +
                "<name>My name</name></storageInfo></controller></controllers>";
        XStream stream = new XStream();
        stream.processAnnotations(ControllerList.class);
        InputStream in = new ByteArrayInputStream(xml.getBytes());
        try {
            InputStreamReader rdr = new InputStreamReader(in, "UTF-8");
            ControllerList controllers = (ControllerList) stream.fromXML(rdr);
        } catch (UnsupportedEncodingException e) {
        }
    }
}

Upvotes: 2

Views: 919

Answers (1)

Bruno Ribeiro
Bruno Ribeiro

Reputation: 6197

XStream CollectionConverter does not supports java.util.Collection. So, you can try in two ways:

  1. replace Collection by List:
import java.util.List;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;

@XStreamAlias("controller")
public class Controller {

    @XStreamImplicit(itemFieldName = "storageInfo")
    private List<BasicInfo> storage;

    public List<BasicInfo> getStorage() {
        return storage;
    }

    public void setStorage(final List<BasicInfo> storage) {
        this.storage = storage;
    }

}

This test should work for the first case:

@Test
public void testControllers() {
    final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><controllers><controller><storageInfo><name>My name</name></storageInfo></controller></controllers>";
    final XStream stream = new XStream();
    stream.processAnnotations(ControllerList.class);
    final ControllerList controllers = (ControllerList) stream.fromXML(xml);

    final List<Controller> colls = controllers.getControllers();
    Assert.assertEquals(colls.size(), 1);

    final Controller coll = colls.get(0);

    final List<BasicInfo> infos = coll.getStorage();

    Assert.assertEquals(infos.size(), 1);

    final BasicInfo info = infos.get(0);

    Assert.assertEquals(info.getName(), "My name");
}
  1. Add a default implementation to java.util.Collection. This test should work:
@Test
public void testControllers() {
    final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><controllers><controller><storageInfo><name>My name</name></storageInfo></controller></controllers>";
    final XStream stream = new XStream();
    stream.processAnnotations(ControllerList.class);
    stream.addDefaultImplementation(ArrayList.class, Collection.class);

    final ControllerList controllers = (ControllerList) stream.fromXML(xml);

    final List<Controller> colls = controllers.getControllers();
    Assert.assertEquals(colls.size(), 1);

    final Controller coll = colls.get(0);

    final Collection<BasicInfo> infos = coll.getStorage();

    Assert.assertEquals(infos.size(), 1);

    for (final BasicInfo info : infos) {
        Assert.assertEquals(info.getName(), "My name");
    }

}

Upvotes: 2

Related Questions