I need to parse XML, containing node child, which shares the name subject for attribute of type String and unwrapped collection of type Subject.
Method setSubject(Object value) checks the type of the value given and maps it to either String or Subject field internally.
Method XmlMapper.convertValue(Object from, Class<T> to) fails on second attempt with the com.fasterxml.jackson.databind.JsonMappingException because node element is being treated as LinkedHashMap instead of ArrayList expected.
com.fasterxml.jackson.databind.JsonMappingException: Cannot deserialize value of type
java.util.ArrayList[com.example.MyTest$Node]from Object value (tokenJsonToken.START_OBJECT) at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: com.example.MyTest$Root["child"]-]com.example.MyTest$Child["subject"])
Any ideas why is working that way?
@Test
void syntheticTest() throws JsonMappingException, JsonProcessingException {
String xml;
Root root;
// #1
xml = """
<root>
<child subject="first subject">
<subject>
<node param="value1" />
<node param="value2" />
</subject>
</child>
</root>
""";
root = mapper.readValue(xml, Root.class);
assertEquals(2, root.getChild().getSubjectObj().getNodes().size());
// #2
xml = """
<root>
<child subject="second subject">
<subject>
<node param="value1" />
</subject>
</child>
</root>
""";
root = mapper.readValue(xml, Root.class);
assertEquals(1, root.getChild().getSubjectObj().getNodes().size());
}
@Getter
@Setter
public static class Root {
private Child child;
}
@Getter
public static class Child {
private String subjectStr;
private Subject subjectObj;
public void setSubject(Object value) {
if (value instanceof String str) {
subjectStr = str;
} else {
subjectObj = mapper.convertValue(value, Subject.class); // <- #2 com.fasterxml.jackson.databind.JsonMappingException
}
}
}
@Getter
@Setter
public static class Subject {
@JsonProperty("node")
@JacksonXmlElementWrapper(useWrapping = false)
private List<Node> nodes;
}
@Getter
@Setter
public static class Node {
private String param;
}