Десериализация пространств имен xml с помощью Jackson & Kotlin

У меня есть элемент xml с двумя пространствами имен, и я не могу их прочитать с помощью jackson.

<Person xmlns="http://some.namespace.com" xmlns:ns0="http://some.other.namespace.com">
    <name>John</name>
</Person>
internal data class Person(
    val name: String,
    @get:JacksonXmlProperty(isAttribute = true)
    val xmlns: String,
    @get:JacksonXmlProperty(isAttribute = true, localName="xmlns:ns0")
    val ns0: String
)

При чтении XML с Джексоном я получаю сообщение об ошибке, говорящее, что оба пространства имен должны быть обнуляемыми.

Я пробовал с некоторыми вариантами, такими как атрибуты в теле класса и с атрибутом пространства имен, например

    @JacksonXmlProperty(isAttribute = true, localName = "ns0", namespace = "xmlns")
    var ns0: String? = null

Это картограф, которым я пользуюсь

val mapper: XmlMapper = XmlMapper().apply {
        registerModule(KotlinModule())
        setSerializationInclusion(JsonInclude.Include.NON_NULL)
    }

Как я могу снова прочитать и написать этот xml и сделать их идентичными?


person talabes    schedule 27.05.2019    source источник


Ответы (2)


Параметры XML xmlns="...." и xmlns:prefix="...." являются определениями пространства имен XML. Они не являются атрибутами XML, даже если выглядят так.

Следовательно, вы не должны определять атрибуты POJO, соответствующие этим. Вместо этого вы используете параметр namespace для @JacksonXmlProperty. Таким образом, ваш класс Person будет выглядеть так:

internal data class Person(
    @get: JacksonXmlProperty(isAttribute=true, localName="name", namespace="http://some.namespace.com")
    val name: String
)
person Thomas Fritsch    schedule 27.05.2019
comment
Спасибо, Томас, но пространство имен ns0 исчезнет, ​​если я верну XML. Я не контролирую xml, и мне нужно, чтобы он имел те же пространства имен. - person talabes; 27.05.2019
comment
В вашем примере ввода XML префикс пространства имен ns0 нигде не используется. Поэтому не имеет значения, что он не отображается в выводе XML. Если входные данные XML действительно используют его (например, <ns0:name>John</ns0:name>), то он также появится в выходных данных XML. - person Thomas Fritsch; 27.05.2019
comment
Я понимаю, купите в моем случае, что ns нужен целевой системе (потому что есть атрибут, который содержит ns (например, <name type="ns0:something">John</name>). Я знаю, что это не имеет смысла xml, но я не могу контролировать ни исходный xml, ни потребности целевой системы.Есть ли способ форсировать ns, несмотря на то, что он не используется? - person talabes; 27.05.2019

Я решил свою проблему, установив свойство для XMLInputFactory следующим образом:

val inputFactory = XMLInputFactory.newFactory()
inputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false)
XmlMapper(inputFactory).apply {
   registerModule(KotlinModule())
}

В этом случае вы можете моделировать все пространства имен и делать то, что хотите. Дело раскрыто.

person talabes    schedule 28.05.2019