Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XmlMapper fails to parse XML array when the array only has one level #498

Closed
ericcwlaw opened this issue Oct 27, 2021 · 6 comments
Closed
Milestone

Comments

@ericcwlaw
Copy link

ericcwlaw commented Oct 27, 2021

Version used

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.13.0</version>
</dependency>

Java versions tested

OpenJDK 1.8, 11 and 16

Test data

<?xml version="1.0" encoding="UTF-8"?>
<result>
  <hello>world</hello>
  <lists>1</lists>
  <lists>2</lists>
  <lists></lists>
  <lists>
    <inner>internal</inner>
    <time>2021-10-27T21:18:46.217Z</time>
  </lists>
  <lists>3</lists>
  <lists>test</lists>
  <lists></lists>
  <single>one</single>
</result>

Incorrect result
by XmlMapper readValue(string, Map.class) method

{
 "hello": "world",
 "single": "one",
 "lists": "test"
}

The array (as "lists" in the test data) contains 6 elements but XmlMapper returns only the last element.

@Martmists-GH
Copy link

Experiencing a similar issue with XML lists:

<?xml version="1.0" encoding="utf-8"?>
<ContentMeta>
    <Type>Application</Type>
    <Id>0x01006fe013472000</Id>
    <Version>0</Version>
    <Content>
        <Type>Program</Type>
        <Id>2b0153c1bb7ceb9cd84e7eb9e0e2288d</Id>
    </Content>
    <Content>
        <Type>Control</Type>
        <Id>32ec02fa4709c28a099d6670590e025b</Id>
    </Content>
</ContentMeta>
data class ContentMeta(
    val type: String,
    val id: String,
    val version: Int,
    val content: Content  // not a list -> gets last
)

mapper.readValue<ContentMeta>(xml)
// => ContentMeta(type="Application", id="0x01006fe013472000", version=0, content=Content(type="Control"))
data class ContentMeta(
    val type: String,
    val id: String,
    val version: Int,
    val content: List<Content>  // list -> fails
)

mapper.readValue<ContentMeta>(xml)
// => Exception in thread "Indexing thread" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `Content` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('Program')

@cowtowncoder cowtowncoder added 2.14 and removed 2.14 labels Nov 4, 2021
@cowtowncoder
Copy link
Member

@ericcwlaw Looks like a bug, yes.

@Martmists-GH Not same issue just because there's List somewhere; please file separate one if you want -- will require pure-Java implementation, however, cannot have Kotlin dependency in this module. Or file against Kotlin module

@cowtowncoder
Copy link
Member

@Martmists-GH quick note: not sure why, but use of nominal target of Object instead of Map seems to result in proper merging. So you may be able to work around the issue on short term.

I will add a failing test first, see if I can figure out what might be causing the problem. I'll also try to see if this might be different with root values (where generic types are a constant source of issues) vs. "Map as a property" (wrapper POJO with single Map valued property).

cowtowncoder added a commit that referenced this issue Jan 30, 2022
@cowtowncoder cowtowncoder added the has-failing-test Indicates that there exists a test case (under `failing/`) to reproduce the issue label Jan 30, 2022
@cowtowncoder
Copy link
Member

Ok another little note: use of Wrapper POJO like:

public class MapHolder {
  public Map<String,Object> map;
}

also changes things so that binding works as expected.

So the problem affects only the specific case of Root value being bound as Map.

@cowtowncoder cowtowncoder added 2.14 and removed 2.13 labels May 17, 2022
@cowtowncoder
Copy link
Member

Note to self: use of "untyped" target (Object.class) is due to UntypedObjectDeserializer handling duplicate squashing but Map one not. Ugh.
Will file an issue against jackson-databind to try to fix.

@cowtowncoder cowtowncoder removed the has-failing-test Indicates that there exists a test case (under `failing/`) to reproduce the issue label Oct 6, 2022
@cowtowncoder cowtowncoder added this to the 2.14.0-rc2 milestone Oct 6, 2022
@cowtowncoder
Copy link
Member

Fixed via jackson-databind; will work in 2.14.0-rc2 (and 2.14.0 final)

@cowtowncoder cowtowncoder changed the title XmlMapper fails to parse XML array when the array only has one level XmlMapper fails to parse XML array when the array only has one level Oct 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants