Jackson 2.9.5 case sensitive problem

2,191 views
Skip to first unread message

Marte Marte

unread,
Apr 5, 2018, 1:38:53 PM4/5/18
to jackson-user
Hello everyone,
  I hope to find some help on this "strange" issue or a different look to this problem.

Let's start from a simple xsd, like this one:


<xs:schema xmlns:fls="http://flussi.mds.it/flsassdom_1"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://flussi.mds.it/flsassdom_1" elementFormDefault="qualified"
attributeFormDefault="unqualified">
    <xs:element name="FlsAssDom_1">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="fls:Residenza" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="Residenza">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="ASL" type="fls:codASL"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:simpleType name="codASL">
        <xs:restriction base="xs:string">
            <xs:pattern value="[a-zA-Z0-9]{3}"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>


From this xsd from Eclipse using "default" jaxb implementation I have generated corresponding classes.
Now, if I start from following example xml:

<?xml version="1.0" encoding="utf-8"?>
<FlsAssDom_1 xmlns="http://flussi.mds.it/flsassdom_1">
    <Residenza>
      <ASL>123</ASL>
    </Residenza>
</FlsAssDom_1>

And try to use it with Jackson:


public class MapperTest {

    @Test
    public void simpleMapperTest() throws JsonParseException, JsonMappingException, IOException {
        XmlMapper mapper = new XmlMapper();
        File f = new File(this.getClass().getResource("example.xml").getFile());

        FlsAssDom1 read = mapper.readValue(f, FlsAssDom1.class);

        assertTrue(read != null);
    }

}


And what I receive is the following exception:


com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Residenza" (class it.test.model.FlsAssDom1), not marked as ignorable (one known property: "residenza"])
 at [Source: (File); line: 4, column: 9] (through reference chain: it.test.model.FlsAssDom1["Residenza"])
    at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:822)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1152)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1582)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1560)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2890)
    at MapperTest.simpleMapperTest(MapperTest.java:21)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

My generated class "" is the following:


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "residenza"
})
@XmlRootElement(name = "FlsAssDom_1")
public class FlsAssDom1 {

    @XmlElement(name = "Residenza", required = true)
    protected List<Residenza> residenza;


My generated class "Residenza" is the following:


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "asl"
})
@XmlRootElement(name = "Residenza")
public class Residenza {

    @XmlElement(name = "ASL", required = true)
    protected String asl;

    /**
     * Recupera il valore della proprietà asl.
     *
     * @return
     *     possible object is
     *     {@link String }
     *    
     */
    public String getASL() {
        return asl;
    }

    /**
     * Imposta il valore della proprietà asl.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *    
     */
    public void setASL(String value) {
        this.asl = value;
    }

}


As you can see, in xsd the field is "Residenza", in xml is "Residenza" and in the XmlRootElement is "Residenza". In the class "FlsAssDom1 " there is a:

@XmlType(name = "", propOrder = {
    "residenza"
})

with lowercase.

After some investigation, I have tried enabling the feature "MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES":


    @Test
    public void caseInsensitiveFeatureMapperTest() throws JsonParseException, JsonMappingException, IOException {
        XmlMapper mapper = new XmlMapper();
        mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
        File f = new File(this.getClass().getResource("example.xml").getFile());

        FlsAssDom1 read = mapper.readValue(f, FlsAssDom1.class);

        assertTrue(read != null);
    }

And the error is different:


com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `it.test.model.Residenza` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('123')
 at [Source: (File); line: 4, column: 12] (through reference chain: it.test.model.FlsAssDom1["Residenza"]->java.util.ArrayList[0])
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1031)
    at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1366)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:286)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:136)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2890)
    at MapperTest.caseInsensitiveFeatureMapperTest(MapperTest.java:34)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)


My ideas:

1) generate classes from xsd using Eclipse Oxygen.3 Release (4.7.3)  is broken somewhere
2) it's better if I use some sort of bindings during xsd->java generation ? But xsd and xml are consistent each other
3) do you suggest to open an issue on github and report this problem and ask for support? I can provide a self-contained project that reproduce the problem

thanks in advance

Tatu Saloranta

unread,
Apr 6, 2018, 6:09:01 PM4/6/18
to jackson-user
Ok, couple of notes:

1. Jackson does not know or care about XSD: the only thing that
matters is generated Java class(es)
2. If using JAXB annotations, make sure to register
JAXBAnnotationIntrospector: by default Jackson only uses its own
annotations;
but `AnnotationIntrospector` allows supporting non-native
annotation sets too, such as JAXB ones.
3. A good way to troubleshoot structural mismatch is to take an
object, then serialize it (write) as xml, see if that match, and if
not, how
4. A common structural mismatch is for List/Collection values,
regarding whether there is a wrapper element for property (in addition
to elements per value) -- by default JAXB DOES NOT use them, and by
default Jackson DOES use wrappers. You may want to
disable use of wrappers either on per-property basis (there's a
Jackson annotation for that), or, as default for all properties.

I hope this helps,

-+ Tatu +-
> --
> You received this message because you are subscribed to the Google Groups
> "jackson-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to jackson-user...@googlegroups.com.
> To post to this group, send email to jackso...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Marte Marte

unread,
Apr 9, 2018, 3:37:21 AM4/9/18
to jackson-user
Thanks for suggestion, point 2) solve problem for me!

I've made with my test case an example repo here: https://github.com/albertotn/Jackson-dataformat-xml-test
Reply all
Reply to author
Forward
0 new messages