Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Support mapping xsi:nil marked elements as nulls (JsonToken.VALUE_NULL) #354

Closed
cowtowncoder opened this issue Aug 12, 2019 · 5 comments
Closed
Milestone

Comments

@cowtowncoder
Copy link
Member

cowtowncoder commented Aug 12, 2019

Although XML specification does not specify semantics for xsi:nil (with appropriate namespace), XML Schema specification does, and so some Java XML libraries (including JAXB) support mapping it into nulls.
(there is the related question of generation/writing, but this issue covers only read side).

It would be good if Jackson did same mapping automatically.

For background, see

@cowtowncoder
Copy link
Member Author

Note: one follow-up task, #359 -- but closed for 2.x

@cowtowncoder cowtowncoder changed the title Support mapping xsi:nul marked elements as nulls (JsonToken.VALUE_NULL) Support mapping xsi:nil marked elements as nulls (JsonToken.VALUE_NULL) Sep 27, 2019
@henrik242
Copy link

henrik242 commented Dec 16, 2019

@cowtowncoder I have a test that's failing after upgrading to 2.10.x. It worked fine with 2.9.x. Any idea if this issue is related, and how I can configure the mapper to fix it?

The test (kotlintest):

data class Silly(val hey: String? = null, val ho: String? = null)

"should encode inner tag with unexpected nil attribute" {
    val xml = """
        <Silly xmlns:a="http://www.w3.org/2001/XMLSchema-instance" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <a:Hey i:nil="true"/>
            <a:Ho>to</a:Ho>
        </Silly>"""

    val res = xml.parseXml<Silly>()

    res shouldBe Silly("", "to")
}

The failure:

org.opentest4j.AssertionFailedError: expected: Silly(hey=, ho=to) but was: Silly(hey=null, ho=null)
Expected :Silly(hey=, ho=to)
Actual   :Silly(hey=null, ho=null)

I'm fine with hey being null, but it's especially surprising that ho is null as well.

The parseXml() implementation:


import com.fasterxml.jackson.databind.DeserializationFeature.*
import com.fasterxml.jackson.databind.MapperFeature.*

private fun xmlFactory() = XmlFactory(newInstance().apply {
        setProperty(IS_NAMESPACE_AWARE, true)
})

private val jacksonXmlModule = JacksonXmlModule().apply {
        setDefaultUseWrapper(false)
        setXMLTextElementName("textContent")
}

private fun createMapper() = XmlMapper(xmlFactory(), jacksonXmlModule)
        .registerKotlinModule()
        .configure(ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
        .configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
        .configure(ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
        .configure(ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)

inline fun <reified T : Any> String.parseXml(): T = createMapper().readValue(this, T::class.java)

@henrik242
Copy link

It works if I replace the http://www.w3.org/2001/XMLSchema-instance namespace with something else. Is there a way of disabling this feature? I guess this is related to #358 somehow.

@cowtowncoder
Copy link
Member Author

It is probably related to the way xsi:nil is detected, yes, although things previously working may just be due to luck (i.e. not necessarily due to explicit support).
I think it's worth creating separate issue; it would be nice if reproduction is in pure Java (since tests can not depend on Kotlin, outside of Kotlin module), but I can probably convert them if need be.

@henrik242
Copy link

@cowtowncoder Created separate issue with test project in #378

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants