Trouble with Lists when ignoring unknown elements

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Trouble with Lists when ignoring unknown elements

Kay Masslow

Hi all,

The FAQ recommends "implement a custom mapper to ignore unknown fields
automatically (see acceptance test
customMapperTest.testCanBeUsedToOmitUnexpectedElements())". However
using this code seems to cause trouble with handling of collections.
Am I doing something wrong here? Using XStream 1.4.4 Please see JUnit
4 code below: testFailsWithUnknownElements() notNull-Assertion fails
because the List is not initialized.

Thanks and regards,

Kay

import static org.junit.Assert.*;
import java.util.List;
import org.junit.Test;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.mapper.MapperWrapper;

class Item { String Value; }
class Root { List<Item> items; }

public class TestIgnoreUnknownElements {

    void initXstream(XStream xstream) {
        xstream.alias("Root", Root.class);
        xstream.alias("Item", Item.class);
        xstream.addImplicitCollection(Root.class, "items", Item.class);
    }

    void doAssertions(Root root) {
        assertNotNull(root.items);
        assertEquals(1, root.items.size());
        assertTrue(root.items.get(0).Value.equals("helloworld"));
    }

    @Test
    public void testOKWithoutUnknownElements() {
        String xml ="<Root><Item><Value>helloworld</Value></Item></Root>";

        XStream xstream = new XStream();
        initXstream(xstream);
        doAssertions((Root) xstream.fromXML(xml));
    }

    @Test
    public void testFailsWithUnknownElements() {
        String xml
="<Root><unknown/><Item><Value>helloworld</Value></Item></Root>";

        /* From
https://fisheye.codehaus.org/browse/xstream/tags/XSTREAM_1_4_4/xstream/src/test/com/thoughtworks/acceptance/CustomMapperTest.java?hb=true
 */
        XStream xstream = new XStream() {

            protected MapperWrapper wrapMapper(MapperWrapper next) {
                return new MapperWrapper(next) {

                    public boolean shouldSerializeMember(Class
definedIn, String fieldName) {
                        return definedIn != Object.class ?
super.shouldSerializeMember(definedIn, fieldName) : false;
                    }

                };
            }

        };
        initXstream(xstream);
        doAssertions((Root) xstream.fromXML(xml));
    }
}

Reply | Threaded
Open this post in threaded view
|

Re: Trouble with Lists when ignoring unknown elements

Jörg Schaible-2
Hi Kay,

Kay Masslow wrote:

> Hi all,
>
> The FAQ recommends "implement a custom mapper to ignore unknown fields
> automatically (see acceptance test
> customMapperTest.testCanBeUsedToOmitUnexpectedElements())". However
> using this code seems to cause trouble with handling of collections.

You get trouble with *implicit* collections/arrays.

> Am I doing something wrong here?

Nothing, but the custom mapper interferes with the handling of the implicit
collection. The problem is, that those elements ("Item" in your case) are no
fields of Root. The reflection converter will now ask the mapper if it
should deserialize a field named "Item" and the custom mapper says no now,
because that field is not declared anywhere in the class hierarchy. If the
converter is told, not to deserialize this item, it stops .. and will not
look for a possible implicit element.

> Using XStream 1.4.4 Please see JUnit
> 4 code below: testFailsWithUnknownElements() notNull-Assertion fails
> because the List is not initialized.

This is another caveat of implicit collections (covered by FAQ): If no
element was found, the collection itself is not initialized i.e. the field
keeping the collection instance is null. Because of the "implicit"
declaration of the collection, XStream can no longer separate between an
empty collection and null, because the collection has no representation in
the XML at all. You may use a readResolve method to initialize it with an
empty collection (also FAQ).

It is possible to implement the custom mapper for implicit collections
though, but it costs a bit more runtime:

new MapperWrapper(next) {
  public boolean shouldSerializeMember(Class definedIn, String fieldName) {
    if (getImplicitCollectionDefForFieldName(definedIn, fieldName) != null)
{
      return true;
    }
    return definedIn != Object.class ?
      super.shouldSerializeMember(definedIn, fieldName) : false;
    }
  }

Cheers,
Jörg


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Trouble with Lists when ignoring unknown elements

Jörg Schaible-2
Jörg Schaible wrote:

> Hi Kay,
>
> Kay Masslow wrote:
>
>> Hi all,
>>
>> The FAQ recommends "implement a custom mapper to ignore unknown fields
>> automatically (see acceptance test
>> customMapperTest.testCanBeUsedToOmitUnexpectedElements())". However
>> using this code seems to cause trouble with handling of collections.
>
> You get trouble with *implicit* collections/arrays.
>
>> Am I doing something wrong here?
>
> Nothing, but the custom mapper interferes with the handling of the
> implicit collection. The problem is, that those elements ("Item" in your
> case) are no fields of Root. The reflection converter will now ask the
> mapper if it should deserialize a field named "Item" and the custom mapper
> says no now, because that field is not declared anywhere in the class
> hierarchy. If the converter is told, not to deserialize this item, it
> stops .. and will not look for a possible implicit element.
>
>> Using XStream 1.4.4 Please see JUnit
>> 4 code below: testFailsWithUnknownElements() notNull-Assertion fails
>> because the List is not initialized.
>
> This is another caveat of implicit collections (covered by FAQ): If no
> element was found, the collection itself is not initialized i.e. the field
> keeping the collection instance is null. Because of the "implicit"
> declaration of the collection, XStream can no longer separate between an
> empty collection and null, because the collection has no representation in
> the XML at all. You may use a readResolve method to initialize it with an
> empty collection (also FAQ).
>
> It is possible to implement the custom mapper for implicit collections
> though, but it costs a bit more runtime:
>
> new MapperWrapper(next) {
>   public boolean shouldSerializeMember(Class definedIn, String fieldName)
>   {
>     if (getImplicitCollectionDefForFieldName(definedIn, fieldName) !=
>     null)
> {
>       return true;
>     }
>     return definedIn != Object.class ?
>       super.shouldSerializeMember(definedIn, fieldName) : false;
>     }
>   }

Sorry, this modification does not work either ... :-/

- Jörg


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Trouble with Lists when ignoring unknown elements

Jörg Schaible-2
Jörg Schaible wrote:

> Jörg Schaible wrote:
>
>> Hi Kay,
>>
>> Kay Masslow wrote:
>>
>>> Hi all,
>>>
>>> The FAQ recommends "implement a custom mapper to ignore unknown fields
>>> automatically (see acceptance test
>>> customMapperTest.testCanBeUsedToOmitUnexpectedElements())". However
>>> using this code seems to cause trouble with handling of collections.
>>
>> You get trouble with *implicit* collections/arrays.
>>
>>> Am I doing something wrong here?
>>
>> Nothing, but the custom mapper interferes with the handling of the
>> implicit collection. The problem is, that those elements ("Item" in your
>> case) are no fields of Root. The reflection converter will now ask the
>> mapper if it should deserialize a field named "Item" and the custom
>> mapper says no now, because that field is not declared anywhere in the
>> class hierarchy. If the converter is told, not to deserialize this item,
>> it stops .. and will not look for a possible implicit element.
>>
>>> Using XStream 1.4.4 Please see JUnit
>>> 4 code below: testFailsWithUnknownElements() notNull-Assertion fails
>>> because the List is not initialized.
>>
>> This is another caveat of implicit collections (covered by FAQ): If no
>> element was found, the collection itself is not initialized i.e. the
>> field keeping the collection instance is null. Because of the "implicit"
>> declaration of the collection, XStream can no longer separate between an
>> empty collection and null, because the collection has no representation
>> in the XML at all. You may use a readResolve method to initialize it with
>> an empty collection (also FAQ).
>>
>> It is possible to implement the custom mapper for implicit collections
>> though, but it costs a bit more runtime:
>>
>> new MapperWrapper(next) {
>>   public boolean shouldSerializeMember(Class definedIn, String fieldName)
>>   {
>>     if (getImplicitCollectionDefForFieldName(definedIn, fieldName) !=
>>     null)
>> {
>>       return true;
>>     }
>>     return definedIn != Object.class ?
>>       super.shouldSerializeMember(definedIn, fieldName) : false;
>>     }
>>   }
>
> Sorry, this modification does not work either ... :-/

Latest trunk has no method XStream.ignoreUnknownElements()

- Jörg


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email