I have "a not nice looking" XML. (yes it's valid but different to the ones I normally get and where I know how to deal with it)
Normally I wanted so see something like:
<Parent....>
<Books>
<Book ...>
<Book ...>
<Book ...>
</Books>
</Parent>
my Data Class for the abvoe XML would look like this:
data class Parent(
@JacksonXmlProperty(localName = "Books")
@JacksonXmlElementWrapper
var books: List<Book>
)
data class Book(
.....
)
but unfortunately our incoming XML looks like this:
<Parent....>
<Book ...>
<Something>
<Book ....>
<Something>
<Book ...>
</parent>
So I'm struggling with matching this with a normal Jackson Mapper, without using a custom one. (and if I need a custom one, how it needs to look like?)
My mapper looks like this:
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)
For deserializing such an XML there's two tricks you can use:
List<Book>
, as they are sitting directly in the Parent
More specifically, you can annotate your classes as such to allow deserialization of your example:
@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
)
I uploaded a full example, which uses your Jackson config and sample XML, as a Kotlin Script to GitHub Gist. It also shows the output of the deserialized XML at the bottom.