OK, I just realized that I misdiagnozed the problem. What actually happens is 
that CollectionConverter is initialized with the List type, because that is the 
declared type of the field. The actual type of the field (ArrayList) differs 
from the type with which the converter was initialized, which is why it won't 
work. Here is the canConvert method in CollectionConverter:

    public boolean canConvert(Class type) {
        if (this.type != null) {
            return type.equals(this.type);
        }
        return type.equals(ArrayList.class)
            || type.equals(HashSet.class)
            || type.equals(LinkedList.class)
            || type.equals(Vector.class) 
            || (JVM.is14() && type.getName().equals("java.util.LinkedHashSet"));
    }

this.type is List, and type is ArrayList. Perhaps this would be better?

            return type.isAssignableFrom(this.type);


Here is a complete example:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.StaxDriver;

public class ItemList {

        @XStreamConverter(CollectionConverter.class)
        public List<String> items = new ArrayList<String>();

        public static void main(String[] args) throws FileNotFoundException {
                ItemList ilist = new ItemList();
                ilist.items.add("One");
                ilist.items.add("Two");
                XStream x = new XStream(new StaxDriver());
                x.autodetectAnnotations(true);
                PrintWriter writer = null;
                try {
                        writer = new PrintWriter(new File("items.xml"));
                        x.marshal(ilist, new PrettyPrintWriter(writer));
                } finally {
                        if (writer != null)
                                writer.close();
                }
        }
}

I get an exception with XStream 1.4.6.1:

Exception in thread "main" 
com.thoughtworks.xstream.converters.ConversionException: Explicit selected 
converter cannot handle item
---- Debugging information ----
item-type           : java.util.ArrayList
converter-type      : 
com.thoughtworks.xstream.converters.collections.CollectionConverter
-------------------------------

If I use a custom converter instead:

        @XStreamConverter(MyCollectionConverter.class)
        public List<String> items = new ArrayList<String>();

        public static class MyCollectionConverter extends CollectionConverter {
                public MyCollectionConverter(Mapper mapper) {
                        super(mapper);
                }
        }

then the CollectionConverter is not initialized with a specific type (type == 
null), which leads to a different branch in canConvert.

-----Original Message-----
From: Jörg Schaible [mailto:joerg.schai...@gmx.de] 
Sent: Friday, February 21, 2014 1:36 AM
To: user@xstream.codehaus.org
Subject: [xstream-user] Re: Using CollectionConverter with @XStreamConverter

Hi Dmitry,

depst...@alliedtesting.com wrote:

> Hi,
> 
> When CollectionConverter is used with the @XStreamConverter 
> annotation, the converter is set up so that it will only accept the 
> TreeMap collection type.

?? Sorry, I don't understand, what you try to tell me here.

> This is an odd behavior! Is there any way to suppress this 
> initialization (CollectionConverter has a constructor that doesn't 
> limit it to just one particular type), or to specify some other type, 
> such as ArrayList?
> 
> public class ItemList {
>     @XStreamConverter(value = CollectionConverter.class)
>     public List<String> items;
> }

I don't understand this example either. You setup an own CollectionConverter 
for the list, but that's the default anyway.


> 
> As a workaround, I subclassed CollectionConverter:
> 
> public class ItemList {
>     @XStreamConverter(value = ListCollectionConverter.class)
>     public List<String> items;
> 
>     public static class ListCollectionConverter extends
>     CollectionConverter {
>         public ListCollectionConverter(Mapper mapper) {
>             super(mapper);
>         }
>     }
> }
> 
> This did the trick, but it is very counterintuitive.

Where's the difference?

Maybe you tell me first, what you actually try to accomplish...

- Jörg

Reply via email to