jackson-module-kotlin: InvalidDefinitionException in case of deserialization xml to data class with @JacksonXmlText annotation
Data class example:
@JacksonXmlRootElement(localName = "sms")
@JsonIgnoreProperties(ignoreUnknown = true)
data class Sms(
@set:JacksonXmlProperty(localName = "Phone", isAttribute = true)
var phone: String?,
@JacksonXmlText
var text: String? = ""
)
Corresponding xml:
<sms Phone="435242423412" Id="43234324">Lorem ipsum</sms>
Deserialization causes such output:
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid definition for property `` (of type `proton72.github.com.Sms`): Could not find creator property with name '' (known Creator properties: [Phone, text])
at [Source: (StringReader); line: 1, column: 1]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:62)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadPropertyDefinition(DeserializationContext.java:1446)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.addBeanProps(BeanDeserializerFactory.java:567)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:227)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:137)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:411)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:477)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4178)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3997)
Reproduced on jackson-dataformat-xml and jackson-module-kotlin 2.9.4 both.
About this issue
- Original URL
- State: open
- Created 6 years ago
- Reactions: 7
- Comments: 16 (8 by maintainers)
Commits related to this issue
- unclear why Github #138 fails, test case marked ignore showing the problem — committed to FasterXML/jackson-module-kotlin by apatrida 6 years ago
Outdated, I recommend to use
setXMLTextElementName.Based on the above discovery here’s another workaround (instead of using JsonNode):
Note: this is not a solution as the field will be writable (
var,private sethelps a bit, but still), will have no construct-time validation that the field is set (lateinit), and the field will not play indata classoperations likeequals,toString, and others (it’s not in the primary constructor)!I just found someone on kotlin slack (named Stephan Schroeder) providing a solution :
You need a mapper like this :
and annotate your field like this:
This works for me with jackson 2.10.1. Slack user claims it works with jackson 2.9.9
Genius, it works for me too! Thank you very much for sharing @ctruchi! Note @ctruchi
@JacksonXmlTextdoesn’t have an effect withsetXMLTextElementNamewhen deserializing only. However it is required for serialization.Following @ctruchi’s example this also works, with the benefit of not mixing XML and JSON annotations:
@cowtowncoder To move this a bit forward…
Here’s a base repro:
removing
@JacksonXmlTextworks as expected, but obviously doesn’t deserialize the text:Commenting/removing the Kotlin Attribute class and using this instead works:
Getting a bit more close to Kotlin data classes fails the same way as Kotlin:
Note: removing
registerModule(KotlinModule())makes no difference.If we solve the Java version to work (maybe the annotations are wrong), we could figure out how to do the same in Kotlin.
I was using the
innerTextworkaround mentioned above but after updating to a newer version of the library, this no longer worked for me either.Using version 2.12.6 of
jackson-dataformat-xmlandjackson-module-kotlinI had to move the property out of the constructor (and make it a nullable var), as a result had to stop using a data class as these require at least one constructor parameter. Using the@JacksonXmlTextmeant I didn’t need theinnerTextanymore. This was for deserializing only as this was all I required.For this XML:
The following worked for me:
I was still able to use the builder method for creating the XmlMapper, without the need for
nameForTextElement("innerText").Haven’t tried this on 2.13.x and above versions yet.