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.

Parsing empty tags without default no-arguments constructor fails in 2.14

See original GitHub issue

As 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:

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:1
  • Comments:14 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
cowtowncodercommented, Nov 21, 2022

@henrik242 Ok, I think that what you can do is to add @JsonCreator(mode = JsonCreator.Mode.DELEGATING) for constructor of Inner. 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 indicate mode 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.

0reactions
cowtowncodercommented, Nov 22, 2022

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 force mode = Mode.DELEGATING for specific inner classes; detect cases where it is needed, return. I don’t remember off-hand which method in AnnotationIntrospector but shouldn’t be too hard to find.

Read more comments on GitHub >

github_iconTop 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 >

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