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;
}