Parsing empty tags without default no-arguments constructor fails in 2.14
See original GitHub issueAs in https://github.com/FasterXML/jackson-dataformat-xml/issues/491, I’ve found an additional issue where parsing empty tags without default constructor fails. This worked in 2.11.3, but has failed since.
Check should_parse_empty_tag_without_default_constructor() in https://github.com/henrik242/jackson-xml-problem/blob/no-string-argument/src/test/java/jackson/xml/NoStringArgumentTest.java#L37
Test (java):
@Test
void should_parse_empty_tag_without_default_constructor() {
String xml = "<outer><inner></inner></outer>";
Outer res = XmlTool.parseOuter(xml);
assertEquals(res, new Outer(null)); // SUCCESS in Jackson 2.11.x, but FAIL in 2.14.x
}
Code (kotlin):
object XmlTool {
val xmlIn = XMLInputFactory.newInstance()
val factory = XmlFactory(xmlIn)
val xmlModule = JacksonXmlModule()
val mapper = XmlMapper(factory, xmlModule).registerKotlinModule()
@JvmStatic
fun parseOuter(xml: String?): Outer = mapper.readValue(xml, Outer::class.java)
data class Inner(val code: String?)
data class Outer(val inner: Inner?)
}
Fails with:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `jackson.xml.XmlTool$Inner` (although at least one Creator exists): no default no-arguments constructor found
at [Source: (StringReader); line: 1, column: 15] (through reference chain: jackson.xml.XmlTool$Outer["inner"])
at app//com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at app//com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1733)
at app//com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1358)
at app//com.fasterxml.jackson.databind.deser.ValueInstantiator.createUsingDefault(ValueInstantiator.java:248)
at app//com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createUsingDefault(StdValueInstantiator.java:275)
at app//com.fasterxml.jackson.databind.deser.BeanDeserializerBase.getEmptyValue(BeanDeserializerBase.java:1042)
at app//com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromEmptyString(StdDeserializer.java:322)
at app//com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromString(StdDeserializer.java:270)
at app//com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1500)
at app//com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:197)
at app//com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:187)
at app//com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:542)
at app//com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:564)
at app//com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:439)
at app//com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1405)
at app//com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:352)
at app//com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:185)
at app//com.fasterxml.jackson.dataformat.xml.deser.XmlDeserializationContext.readRootValue(XmlDeserializationContext.java:91)
at app//com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4697)
at app//com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3652)
at app//com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3620)
at app//jackson.xml.XmlTool.parseOuter(XmlTool.kt:22)
at app//jackson.xml.NoStringArgumentTest.should_parse_empty_tag_without_default_constructor(NoStringArgumentTest.java:39)
at java.base@11.0.16.1/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base@11.0.16.1/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base@11.0.16.1/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base@11.0.16.1/java.lang.reflect.Method.invoke(Method.java:566)
at app//org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
at app//org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at ...
This is the exact same issue as mentioned in https://github.com/FasterXML/jackson-module-kotlin/issues/396, and is already covered a couple of places with existing failing tests:
- https://github.com/FasterXML/jackson-integration-tests/blob/master/src/test/kotlin/com/fasterxml/jackson/failing/Jackson212MissingConstructorTest.kt (see https://github.com/FasterXML/jackson-integration-tests/pull/7)
- https://github.com/FasterXML/jackson-module-kotlin/blob/master/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/github/failing/Github396.kt
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:14 (9 by maintainers)
Top Results From Across the Web
2.12.x regression: no default no-arguments constructor found ...
I have this Kotlin object which parses an XML into a data class: ... Parsing empty tags without default no-arguments constructor fails in...
Read more >ObjectMapper (jackson-databind 2.14.1 API) - javadoc.io
Constructs instance that uses specified JsonFactory for constructing necessary JsonParser s and/or JsonGenerator s.
Read more >SML/NJ Error Messages - Yale FLINT Group
This error occurs when type constructors with incompatible equality properties are equated by sharing constraints. When this happens, the signature is not ......
Read more >Parse empty tag - java - Stack Overflow
Empty element (such as <tag/>) will be reported with two separate events: START_TAG, END_TAG. So it does not enter case XmlPullParser.TEXT: tag.
Read more >XML::Simple - An API for simple XML files - metacpan.org
If your needs are not so simple, this may not be the module for you. ... allows you to pass parameters to the...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@henrik242 Ok, I think that what you can do is to add
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
for constructor ofInner
. In this case String""
will be passed (not null).I will try to see if the alternative (Inner declared to take
PROPERTIES
) could possibly be made to also work but thought I’ll add a note of work-around; and you’d probably want to indicatemode
in either since behavior does generally differ between two modes.EDIT: there is actually another work-around that does work with
PROPERTIES
approach – just add no-argument constructor. That will make deserializer happy.I can’t think of any based on specific fix, but that does not mean someone could not figure out a way around it.
However… I suspect that you could use
AnnotationIntrospector
to essentially forcemode = Mode.DELEGATING
for specific inner classes; detect cases where it is needed, return. I don’t remember off-hand which method inAnnotationIntrospector
but shouldn’t be too hard to find.