java Jackson:使用属性和子标记名称连接解析XML

6tr1vspr  于 2023-04-19  发布在  Java
关注(0)|答案(1)|浏览(165)

我需要解析包含节点child的XML,该节点为String类型的属性和Subject类型的未 Package 集合共享名称subject
方法setSubject(Object value)检查给定值的类型,并在内部将其Map到StringSubject字段。
方法XmlMapper.convertValue(Object from, Class<T> to)在第二次尝试时失败,出现com.fasterxml.Jackson.databind.JsonMappingException,因为node元素被视为LinkedHashMap,而不是预期的ArrayList
com.fasterxml.jackson.databind.JsonMappingException:无法从[Source:未知;字节偏移量:#UNKNOWN](通过参考链:com.example.MyTest$Root[“child”]-]com.example.MyTest$Child[“subject”])
知道为什么会这样吗

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

}
pgvzfuti

pgvzfuti1#

默认情况下,Jackson将只有一个值的列表反序列化为对象而不是数组,这会导致第二个示例失败。将DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY设置为true

mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

参见Jackson deserialize single item into list

相关问题