Search code examples
javaconvertersxstream

How does XStream select its converters?


The only documentation on XStream converters that I can find is on these two pages:

When XStream is parsing XML input, it uses a ConverterLookup (and by default, a DefaultConverterLookup) to lookup which converter to use by class. I'd like to configure my XStream mapper to use my own custom ConverterLookup, but only see a getConverterLookup() method, not a respective setter.

I have an instance where XStream is encountering a Date value in the XML, and returning using the respective DateConverter. I want it to use a different converter, which (I believe) means I need to set/register my own Converter impl. Just can't figure out how to do this. Thanks in advance.


Solution

  • First of all your question is in fact two unrelated questions, I'll try my best to answer them both.

    Converters

    To your second question regarding date conversion. Which in my mind seems to be the reason why you are here.

    The basic way of adding your own converter is rather simple, the method registerConverter should give your a clue. If you are wondering how to implement a Converter I suggest you take a look at one of the many converters already provided by XStream. On an extra note I feel like I must mention the priority of converters.

    The converters can be registered with an explicit priority. By default they are registered with XStream.PRIORITY_NORMAL. Converters of same priority will be used in the reverse sequence they have been registered. The default converter, i.e. the converter which will be used if no other registered converter is suitable, can be registered with priority XStream.PRIORITY_VERY_LOW. XStream uses by default the ReflectionConverter as the fallback converter.

    In other terms, given two converters accepting the same classes, the one who was added last will be used.

    ConverterLookup

    To answer how you can use your ConverterLookup there are two ways which may yield the same results, personally I would go for alternative 2.

    1) Overriding getConverterLookup

        XStream xs = new XStream(){
            @Override
            public ConverterLookup getConverterLookup() {
                return new ConverterLookup() {
    
                    public Converter lookupConverterForType(Class type) {
                        //Do your magic here
                    }
                };
            }
        };
    

    2) Using a Mapper

    In this case I would keep the DefaultMapper and instead implement MapperWrapper's for my new mappings. (Have a look at buildMapper inside of XStream.java to see some of the defaults) Initialize like this:

        ClassLoader classLoader = new ClassLoaderReference(new CompositeClassLoader());
        Mapper mapper = new DefaultMapper(classLoader);
        mapper = new MyOwnMapperWrapper(mapper);
        XStream xs = new XStream(null, mapper, new XppDriver());