Skip to content
New issue

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

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

Already on GitHub? Sign in 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

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

No branches or pull requests

2 participants