【问题标题】:Create custom object from XML with Jackson使用 Jackson 从 XML 创建自定义对象
【发布时间】:2020-05-12 18:46:51
【问题描述】:

我收到大型 XML 文档,我需要从中提取一些字段,然后返回它们。 问题是,当我在查看有关如何使用 Jackson 反序列化对象的各种解决方案时,主要是 1 对 1 映射,或者构建自定义解析器。 我的情况看起来或多或少是这样的

XML

<a>
 <b>
   <c>val</c>
   <d x='val' z='val'><e>val</e><f>lot of irrelevant fields</f></d>
   <g>lot of irrelevant fields</g>
  <b>
<a>

我只对 C X Z E 的值感兴趣,所以在 java 中重新创建整个结构绝对是不行的。实现自定义解析器听起来也有点矫枉过正。 是否有更好的解决方案,IE 通过注释或类似的东西?我记得前段时间,我见过允许通过注释来实现它的库,但现在我在可以使用的库方面受到了一些限制。

【问题讨论】:

  • 您可以构建一个最小的 dto 并使用 @JsonIgnoreProperties(ignoreUnknown = true) 注释类,请参阅 baeldung.com/jackson-deserialize-json-unknown-properties
  • @MichaelKreutz 这个例子是关于 JSON 的,而我正在解析 XML 会起作用吗?我需要在我的 dto 中复制嵌套结构吗?因为它比我的例子稍微复杂一些
  • 我没有尝试过,但我认为它应该也适用于 XML。您需要对您感兴趣的字段的结构进行建模——您可以省略所有其他字段。 baeldung.com/jackson-xml-serialization-and-deserialization 还将 @Json 前缀注释与 xml 解析结合使用...

标签: java xml jackson


【解决方案1】:

最明显的方法是使用 XPath。这包含在 Java 中 - 没有额外的库。虽然有很多方法可以达到你想要的结果,但我写了一个快速测试:

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class XPathDemo {
    private static final String xmlString = "<a>\n" +
            " <b>\n" +
            "   <c>val</c>\n" +
            "   <d x=\"x-val\" z=\"z-val\"><e>e-val</e><f>lot of irrelevant fields</f></d>\n" +
            "   <g>lot of irrelevant fields</g>\n" +
            "  </b>\n" +
            "</a>";

    public static void main(String[] argv) throws IOException, SAXException, ParserConfigurationException, XPathExpressionException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.parse(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));

        XPath xpath = XPathFactory.newInstance().newXPath();
        String c_value = (String) xpath.evaluate("/a/b/c/text()", document, XPathConstants.STRING);
        System.out.println( "value of c is \"" + c_value + "\"");

        String x_value = (String) xpath.evaluate("/a/b/d/@x", document, XPathConstants.STRING);
        System.out.println( "value of x is \"" + x_value + "\"");

        String z_value = (String) xpath.evaluate("/a/b/d/@z", document, XPathConstants.STRING);
        System.out.println( "value of z is \"" + z_value + "\"");

        String e_value = (String) xpath.evaluate("/a/b/d/e/text()", document, XPathConstants.STRING);
        System.out.println( "value of e is \"" + e_value + "\"");
    }
}

输出:

value of c is "val"
value of x is "x-val"
value of z is "z-val"
value of e is "e-val"

这是一个超级简单的例子。当您将相同的基本结构重复多次时,它会变得更加困难。我会阅读XPath Syntax,因为它非常强大,但有时想要得到你想要的东西会有点痛苦。

您应该了解一些注意事项:

  1. 您需要有效的 XML。您发布的内容不是也不会起作用。
  2. 这会将整个文档读入内存。如果你有几千行,那很好。但如果您有 10GB 的文档,您可能需要另一种方式。

【讨论】:

    【解决方案2】:

    您应该查看 DSM 库。它正是你想要的。

    https://github.com/mfatihercik/dsm

    【讨论】:

    • 正如我所提到的,我对其他库不感兴趣。我在非常接近的环境中工作,所以添加一些随机库对我来说不是有效的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多