首页 > 解决方案 > 如何在杰克逊中取消多个嵌套元素?

问题描述

我需要构建一个解析器来将XML文件解析为Java对象。我曾经Jackson这样做并遵循教程中提供的步骤。

教程中有一节“在 XML 中操作嵌套元素和列表”。我跟着它,但不幸的是,我无法获得所有所需元素的所需输出 - 我想输出我所有作者的第一个和最后一个。我只在文件中为我的最后一位作者得到它,XML如下所示:

[{nameList={person={first=Karl, last=S}}}]

我的XML文件看起来像这样。

<sources>
<Doi>123456789</Doi>
<Title>Title</Title>
<author>
    <editor>
        <nameList>
            <person>
                <first>Peter</first>
                <last>Parker</last>
            </person>
        </nameList>
    </editor>
</author>
<Source>
    <SourceType>Book</SourceType>
    <ShortTitle>Book Title</ShortTitle>
    <Author>
        <Editor>
            <NameList />
        </Editor>
    </Author>
</Source>
<author>
    <bookAuthor>
        <nameList>
            <person>
                <first>Karl</first>
                <last>S</last>
            </person>
        </nameList>
    </bookAuthor>
</author>
<Source>
    <SourceType>Journal</SourceType>
    <ShortTitle>ABC Journal</ShortTitle>
</Source>
</sources>

如何取消实现整个 XML 文件?

我的代码如下所示:MyClass.java

private static void jacksonXmlFileToObject() throws IOException {

    System.out.println("jacksonXmlFileToObject");

    InputStream xmlFile = Publication.class.getClassLoader().getResourceAsStream("test.xml");
    ObjectMapper mapper = new XmlMapper();

    // Configure
    mapper
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    try {

        Sources deserializedData = mapper.readValue(xmlFile, Sources.class);

        System.out.println(deserializedData);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

来源.java

@EqualsAndHashCode
@JacksonXmlRootElement(localName = "sources") public class Sources {
@JacksonXmlElementWrapper(localName = "author")
@Getter
@Setter
private Object[] author;

@Override
public String toString() {
    return Arrays.toString(author);
}

public Sources() {
}
}

我会很高兴得到一些帮助。

谢谢!

标签: javaxmlparsingjacksonpojo

解决方案


使用JsonMerge注释。

我最近自己也遇到了类似的问题,发现注释@JsonMerge解决了这个问题。

我稍微简化了 XML:

<sources>
    <author>
        <name>Jack</name>
    </author>
    <source>
        <type>Book</type>
    </source>
    <author>
        <name>Jill</name>
    </author>
    <source>
        <type>Journal</type>
    </source>
</sources>

随着班级AuthorSource

class Author {
    String name;
}
class Source {
    String type;
}

该类Sources如下所示:

class Sources {

    // We prevent each <author> tag to be wrapped in an <authors> container tag
    @JacksonXmlElementWrapper(useWrapping = false)

    // Each element is <author> and not <authors> (and we named our field 'authors')
    @JacksonXmlProperty(localName = "author")

    // This is the property which solves your problem. It causes non-subsequent elements with the
    // same name to be merged into the existing list
    @JsonMerge
    private List<Author> authors;

    @JacksonXmlElementWrapper(useWrapping = false)
    @JacksonXmlProperty(localName = "source")
    @JsonMerge
    private List<Source> sources;
}

推荐阅读