XML Jackson 在 Kotlin 中与一个未真正嵌套的 XML 绑定

XML Jackson binding with a not really nested XML in Kotlin

我“长得不好看”XML。 (是的,它是有效的,但与我通常得到的以及我知道如何处理的不同)

通常我想要这样的东西:

<Parent....>
  <Books>
    <Book ...>
    <Book ...>
    <Book ...>
  </Books>
</Parent> 

abvoe XML 的我的数据 Class 将如下所示:

data class Parent(
    @JacksonXmlProperty(localName = "Books")
    @JacksonXmlElementWrapper
    var books: List<Book> 
)

data class Book(
    .....
    )

但不幸的是我们的传入 XML 看起来像这样:

<Parent....>
    <Book ...>
    <Something>
    <Book ....>
    <Something>
    <Book ...>
</parent> 

所以我正在努力将它与普通的 Jackson Mapper 相匹配,而不是使用自定义的。 (如果我需要一个定制的,它应该是什么样子的?)

我的映射器看起来像这样:

val kotlinModule: KotlinModule = KotlinModule.Builder()
                .strictNullChecks(false)
                .nullIsSameAsDefault(true) // needed, else it will break for null https://github.com/FasterXML/jackson-module-kotlin/issues/130#issuecomment-546625625
                .build()

val xmlMapper =
                XmlMapper(JacksonXmlModule())
                        .registerModule(kotlinModule)
                        .registerModule(JavaTimeModule())
                        .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) // to parse the dates as LocalDate, else parsing error
                        .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
                        .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
                        .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)

要反序列化这样的 XML,您可以使用两个技巧:

  • 明确关闭 List<Book> 的换行,因为它们直接位于 Parent
  • 使用自定义 setter 解决引擎限制,GitHub 问题 #275
  • 中提出的解决方案

更具体地说,您可以这样注释 类 以允许反序列化您的示例:

@JacksonXmlRootElement
class Parent {
    @JacksonXmlProperty(localName = "Book")
    @JacksonXmlElementWrapper(useWrapping = false)
    var books: List<Book> = ArrayList()
        set(value) {
            field = books + value
        }
}

data class Book(
    @JacksonXmlProperty
    val title: String
)

我上传了一个完整的示例,它使用您的 Jackson 配置和示例 XML,作为 GitHub Gist 的 Kotlin 脚本。它还在底部显示了反序列化 XML 的输出。