无法构造 java.util.Collection xstream

Cannot construct java.util.Collection xstream

我在使用 XStream 库解组某些 xml 时遇到问题。相关的 java class 使用 java.util.Collection class 来存储一些属性,我理解这是 XStream 的问题。但是,由于各种原因,我无法将 Java class 更改为使用 ArrayList 之类的东西。有没有一种方法可以使用 XStream 解组 xml,或者我应该搜索其他库来寻找解决方案?

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) {
        }
    }
}

XStreamCollectionConverter不支持java.util.Collection。所以,你可以尝试两种方式:

  1. Collection替换为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;
    }

}

这个测试应该适用于第一种情况:

@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. java.util.Collection 添加默认实现。这个测试应该有效:
@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");
    }

}