1. 概述

在这个教程中,我们将学习如何使用Jackson将XML消息转换为JSON。

对于对Jackson不熟悉的新手,建议先了解下基础内容

2. Jackson简介

我们可以通过三种不同的方式使用Jackson解析JSON:

  • 最常见的是使用ObjectMapper进行数据绑定
  • 第二种是使用TreeTraversingParserJsonNode构建树形数据结构
  • 第三种是通过令牌流式处理树数据结构,使用JsonParserJsonGenerator

值得注意的是,Jackson也支持这两种方法处理XML数据。接下来,我们将探讨如何利用Jackson实现两种格式之间的转换。

3. 依赖项

首先,我们需要在pom.xml文件中添加jackson-databind依赖:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>

这个库将允许我们使用数据绑定API。

其次,需要添加jackson-dataformat-xml以增加Jackson的XML支持:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.13.3</version>
</dependency>

4. 数据绑定

简单来说,数据绑定就是将序列化后的数据直接映射到Java对象上。

为了演示,让我们定义一个带有FlowerColor属性的XML:

<Flower>
    <name>Poppy</name>
    <color>RED</color>
    <petals>9</petals>
</Flower>

这类似于以下Java表示:

public class Flower {
    private String name;
    private Color color;
    private Integer petals;
    // getters and setters
}

public enum Color { PINK, BLUE, YELLOW, RED; }

我们的第一步将是将XML解析为Flower实例。为此,我们需要创建一个XmlMapper实例,它是ObjectMapper的XML等价物,并使用其readValue方法:

XmlMapper xmlMapper = new XmlMapper();
Flower poppy = xmlMapper.readValue(xml, Flower.class);

一旦我们有了Flower实例,我们将使用熟悉的ObjectMapper将其写入JSON:

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(poppy);

最终,我们会得到对应的JSON格式:

{
    "name":"Poppy",
    "color":"RED",
    "petals":9
}

5. 树遍历

有时,直接查看树结构可以提供更大的灵活性,例如当我们不想维护中间类,或者只想转换结构的一部分时。

尽管如此,这也会带来一些权衡。

首先,步骤与使用数据绑定时类似。但这次,我们将使用readTree方法:

XmlMapper xmlMapper = new XmlMapper();
JsonNode node = xmlMapper.readTree(xml.getBytes());

这样,我们就得到了一个JsonNode,它有三个子节点,正如我们预期的:name, color, 和 petals

然后,我们可以再次使用ObjectMapper,但这次传递的是我们的JsonNode

ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(node);

现在,结果与上一个示例略有不同:

{
    "name":"Poppy",
    "color":"RED",
    "petals":"9"
}

仔细观察,我们可以看到petals属性被序列化为字符串,而不是数字!这是因为readTree没有根据明确的定义推断数据类型。

5.1. 限制

Jackson的XML树遍历支持存在一些局限性:

  • Jackson无法区分对象和数组。由于XML缺乏区分对象和对象列表的原生结构,Jackson会将重复的元素合并为单个值。
  • 由于Jackson希望将每个XML元素映射为一个JSON节点,因此它不支持混合内容。

出于这些原因,Jackson官方文档建议不要使用树模型来解析XML

6. 内存约束

这两种方法的共同缺点是,整个XML必须一次性加载到内存中才能进行转换。在Jackson支持按令牌流式处理树结构之前,我们将受限于此,或者需要自己实现,比如使用javax.xml.stream.XMLStreamReader

7. 总结

在这篇教程中,我们简要了解了Jackson如何读取XML数据并将其写入JSON的不同方式。此外,我们也快速浏览了每种支持方法的局限性。

如往常一样,伴随教程的完整源代码可在GitHub上找到。