Open
Description
XML parsing fails when mapping to polymorphic class using JsonTypeInfo.Id.DEDUCTION
and a property of the class is a flat list of elements where @JacksonXmlElementWrapper(useWrapping = false)
is used.
Reproducable example in kotlin showcasing the issue
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
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.ser.ToXmlGenerator
import com.fasterxml.jackson.module.kotlin.KotlinFeature
import com.fasterxml.jackson.module.kotlin.KotlinModule
import org.junit.jupiter.api.Test
class XmlTest {
private val somexml = """
<?xml version="1.0" encoding="UTF-8"?>
<RootTag>
<Response>
<SomeData>hello</SomeData>
<Detail>
<Text>hello world</Text>
</Detail>
</Response>
</RootTag>
""".trimIndent()
@JsonTypeInfo(
use = JsonTypeInfo.Id.DEDUCTION
)
@JsonSubTypes(
JsonSubTypes.Type(value = Response.Success::class),
JsonSubTypes.Type(value = Response.Error::class)
)
sealed class Response {
data class Success(
@JsonProperty("SomeData")
val data: String,
@JacksonXmlProperty(localName = "Detail")
@JacksonXmlElementWrapper(useWrapping = false)
val details: List<NestedClass>,
) : Response()
data class Error(@JsonProperty("ErrCd") val errorCode: String) : Response()
}
data class NestedClass(@JsonProperty("Text") val text: String)
data class WholeResponse(@JsonProperty("Response") val response: Response)
data class WholeResponseWithoutDeduction(@JsonProperty("Response") val response: Response.Success)
@Test
fun `parse xml using deduction`() {
// This test fails although it should pass
ConfiguredXmlMapper.readValue(somexml, WholeResponse::class.java)
}
@Test
fun `parse xml without using deduction`() {
// This test passes which is normal
ConfiguredXmlMapper.readValue(somexml, WholeResponseWithoutDeduction::class.java)
}
}
object ConfiguredXmlMapper : XmlMapper() {
init {
registerModule(KotlinModule.Builder()
.withReflectionCacheSize(512)
.configure(KotlinFeature.NullToEmptyCollection, false)
.configure(KotlinFeature.NullToEmptyMap, false)
.configure(KotlinFeature.NullIsSameAsDefault, false)
.configure(KotlinFeature.SingletonSupport, false)
.configure(KotlinFeature.StrictNullChecks, false)
.build())
}
}
Using these related dependencies
dependencies {
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.13.2")
implementation("com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.13.2")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.1")
implementation("com.fasterxml.jackson.module:jackson-modules-java8:2.13.2")
}