question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

@JacksonXmlElementWrapper doesn’t work with data classes

See original GitHub issue

I want to mapping a xml using kotlin data class, my xml wrapper a list of elements in a wapper node. Xml example: <MyPojo><elements><element value="e1"/></elements></MyPojo>

Here the <element> node is a collection, wrapped in the <elements> node.

When I use the data class to map the ‘MyPojo’ and ‘element’ object and I annotated the collection property with @JacksonXmlElementWrapper and @JacksonXmlProperty it doesn’t work when I try to deserialise form xml. The exception is: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid definition for property elements (of type MyDataPojo): Could not find creator property with name ‘elements’ (known Creator properties: [element])

I use :

  • Java 1.8
  • Kotlin 1.2.31
  • Jackson: 2.9.5

I have write a test to compare the mapping using the standard class and the data class. The standard class test passed, the data class test failed.

import com.fasterxml.jackson.dataformat.xml.XmlMapper
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement
import com.fasterxml.jackson.module.kotlin.KotlinModule
import junit.framework.Assert.assertEquals
import org.junit.Test

/**
 * Mapping the Xml with standard classes
 */
@JacksonXmlRootElement(localName = "MyPojo")
class MyPojo {

  @JacksonXmlElementWrapper(localName = "elements")
  @JacksonXmlProperty(localName = "element")
  var list: List<MyElement>? = null

}

/**
 * Mapping the Xml with standard classes
 */
class MyElement {
  @JacksonXmlProperty(localName = "value", isAttribute = true)
  var value: String? = null

}

/**
 * Mapping the Xml with data classes
 */
@JacksonXmlRootElement(localName = "MyPojo")
data class MyDataPojo (
    @JacksonXmlElementWrapper(localName = "elements")
    @JacksonXmlProperty(localName = "element")
    val list
    : List<MyDataElement>
)

/**
 * Mapping the Xml with data classes
 */
data class MyDataElement (
    @JacksonXmlProperty(localName = "value", isAttribute = true)
    var value: String
)

class TextKotlinXmlWrapper {
  // xml example I want to deserialize
  val xml = """<MyPojo><elements><element value="e1"/></elements></MyPojo>"""

  val mapper = XmlMapper()
      .registerModule(KotlinModule())

  @Test
  @Throws(Exception::class)
  fun test_class() {

    // I create a pojo from the xml using the standard classes
    val pojoFromXml = mapper.readValue(xml, MyPojo::class.java)

    //I create a xml from the pojo
    val xmlFromPojo = mapper.writeValueAsString(pojoFromXml)

    // I compare the original xml with the xml generated from the pojo
    assertEquals(xml, xmlFromPojo)

  }

  @Test
  @Throws(Exception::class)
  fun test_data_class() {

    // I create a pojo from the xml using the data classes
    val pojoFromXml = mapper.readValue(xml, MyDataPojo::class.java)

    //I create a xml from the pojo
    val xmlFromPojo = mapper.writeValueAsString(pojoFromXml)

    // I compare the original xml with the xml generated from the pojo
    assertEquals(xml, xmlFromPojo)

  }

}

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:15
  • Comments:25 (8 by maintainers)

github_iconTop GitHub Comments

10reactions
jespechecommented, Jun 7, 2019

Hi guys, Just in case it helps somebody else, I found a workaround by combining the things mentioned here with a property backed up with a constructor field.

This allow us to still use a data class and avoid writing getters/setters/hashcode/equals.

data class Example(private var _elements: MutableList<String>) {
    @get:JacksonXmlElementWrapper(localName = "elements")
    @get:JacksonXmlProperty(localName = "element")
    var elements
        set(value) { _elements = value }
        get() = _elements
}

It is not too elegant, but it works fine so hopefully it will help.

Thanks guys for helping me figuring it out!

9reactions
joffrey-bioncommented, Jan 20, 2019

FYI, from Kotlin you can specify where the annotation lands, using the get: or field: prefixes between the @ and the annotation name. So the following should work:

data class Example(
        @get:JacksonXmlElementWrapper(localName = "elements")
        @get:JacksonXmlProperty(localName = "element")
        val elements: MutableList<String>
)
Read more comments on GitHub >

github_iconTop Results From Across the Web

Jackson xml 2.9.0: @JacksonXmlElementWrapper not ...
This problem is really tricky because Jackson collects metadata from different places: fields, getters, setters, constructor parameters.
Read more >
Solving the XML Problem with Jackson - Stackify
In order to work with XML, we'll instead use the XmlMapper class. ... This means that it doesn't support writing the raw newlines...
Read more >
Solving the XML Problem with Jackson - DZone
Jackson 2 brings XML data handling to projects, in addition to ... In order to work with XML, we'll instead use the XmlMapper...
Read more >
XML Serialization and Deserialization with Jackson - Baeldung
We'll focus on the basic operation that doesn't require a lot of ... XmlMapper is the main class from Jackson 2.x that helps...
Read more >
FasterXML/jackson-databind - Gitter
next to work on text dataformats & xml, the datatypes-collections. ... data class Rss @JsonCreator constructor (@JsonProperty("channel") val channel: ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found