1. 概述

JSON 和 XML 是数据交换的两种流行格式。在实际应用中,我们常常需要在它们之间进行转换。

在这个教程中,我们将探讨在 Java 中将 JSON 转换为 XML 的不同方法。

2. JSON-Java 库

首先,JSON-Java 库提供了将 JSON 转换为 XML 的简单方法。

2.1. 依赖项

让我们从添加 JSON-Java 的依赖项开始,到我们的 pom.xml 文件:

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20240303</version>
</dependency>

2.2. 代码示例

我们可以使用测试用例来演示转换过程。让我们创建一个测试用例,将 JSON 字符串转换为 XML:

@Test
public void givenJsonString_whenConvertToXMLUsingJsonJava_thenConverted() {
    String jsonString = "{\"name\":\"John\", \"age\":20, \"address\":{\"street\":\"Wall Street\", \"city\":\"New York\"}}";
    JSONObject jsonObject = new JSONObject(jsonString);
    String xmlString = XML.toString(jsonObject);
    Assertions.assertEquals("<address><city>New York</city><street>Wall Street</street></address><name>John</name><age>20</age>", xmlString);
}

如我们所见,可以使用 JSONObjectXML.toString() 方法将 JSON 字符串转换为 XML 字符串。这个方法接受一个 JSONObject 作为参数,并返回一个 XML 字符串。然后我们断言字符串符合预期。

这个方法生成了一个紧凑的 XML 字符串,每个键转换为一个 XML 标签,值是标签的文本内容。

3. Jackson

Jackson 是 Java 中流行的 JSON 库,也可以用于 JSON 到 XML 的转换。

3.1. 依赖项

接下来,我们在 pom.xml 文件中添加 Jackson 的依赖:

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

3.2. 代码示例

接下来,我们将创建一个使用 Jackson 将 JSON 字符串转换为 XML 的测试用例:

@Test
public void givenJsonString_whenConvertToXMLUsingJackson_thenConverted() throws JsonProcessingException {
    String jsonString = "{\"name\":\"John\", \"age\":20, \"address\":{\"street\":\"Wall Street\", \"city\":\"New York\"}}";
    ObjectMapper objectMapper = new ObjectMapper();
    JsonNode jsonNode = objectMapper.readTree(jsonString);
    String xmlString = new XmlMapper().writeValueAsString(jsonNode);
    Assertions.assertEquals("<ObjectNode><name>John</name><age>20</age><address><street>Wall Street</street><city>New York</city></address></ObjectNode>", xmlString);
}

可以看到,我们可以使用 XmlMapper 类的 writeValueAsString() 方法将 JSON 字符串转换为 XML。这个方法接受一个 JsonNode 参数并返回一个 XML 字符串。此外,输出的标签被包裹在一个 ObjectNode 标签内。

3.3. 自定义输出

在之前的例子中,我们看到输出的 XML 字符串没有格式化,没有 XML 声明,且根标签是 ObjectNode。这不符合 XML 标准。我们可以定制输出以使其更易于阅读且符合标准。

让我们向 XmlMapper 对象添加一些配置选项来自定义输出:

@Test
public void givenJsonString_whenConvertToXMLUsingJacksonWithXMLDeclarationAndRoot_thenConverted() throws JsonProcessingException {
    String jsonString = "{\"name\":\"John\", \"age\":20, \"address\":{\"street\":\"Wall Street\", \"city\":\"New York\"}}";
    ObjectMapper objectMapper = new ObjectMapper();
    JsonNode jsonNode = objectMapper.readTree(jsonString);
    
    XmlMapper xmlMapper = new XmlMapper();
    xmlMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
    xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true);
    xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_1_1, true);
    
    String xmlString = xmlMapper.writer().withRootName("root").writeValueAsString(jsonNode);
    
    Assertions.assertEquals("<?xml version='1.1' encoding='UTF-8'?>" + System.lineSeparator() +
      "<root>" + System.lineSeparator() +
      " <name>John</name>" + System.lineSeparator() +
      " <age>20</age>" + System.lineSeparator() +
      " <address>" + System.lineSeparator() +
      " <street>Wall Street</street>" + System.lineSeparator() +
      " <city>New York</city>" + System.lineSeparator() +
      " </address>" + System.lineSeparator() +
      "</root>" + System.lineSeparator(), xmlString);
}

这里我们向 XmlMapper 对象添加了几个配置选项:

  • SerializationFeature.INDENT_OUTPUT 使输出的 XML 字符串更具可读性
  • ToXmlGenerator.Feature.WRITE_XML_DECLARATION 添加 XML 声明到输出的 XML 字符串
  • ToXmlGenerator.Feature.WRITE_XML_1_1 在 XML 声明中添加 XML 版本 1.1
  • withRootName() 设置根标签名为 root,而不是 ObjectNode

如我们所见,输出的 XML 字符串现在已格式化,有 XML 声明,且根标签是 root

4. 使用 Underscore-java

Underscore-java 是一个提供 JSON 转换为 XML 方法的实用库。值得注意的是,它要求 Java 11 或更高版本才能运行。

在 Jackson 示例中,我们需要向 XmlMapper 对象添加一些配置选项,以根据 XML 标准定制输出。Underscore-java 默认遵循 XML 标准,无需这些配置选项。

4.1. 依赖项

首先,让我们在 pom.xml 文件中添加 Underscore-java 的依赖:

<dependency>
    <groupId>com.github.javadev</groupId>
    <artifactId>underscore-java</artifactId>
    <version>1.89</version>
</dependency>

4.2. 代码示例

接下来,让我们创建一个使用 Underscore-java 将 JSON 字符串转换为 XML 的测试用例:

@Test
public void givenJsonString_whenConvertToXMLUsingUnderscoreJava_thenConverted() {
    String jsonString = "{\"name\":\"John\", \"age\":20}";
    String xmlString = U.jsonToXml(jsonString);
    Assertions.assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
      "<root>\n" +
      "  <name>John</name>\n" +
      "  <age number=\"true\">20</age>\n" +
      "</root>", xmlString);
}

如我们所见,可以使用 U.jsonToXml() 方法将 JSON 字符串转换为 XML。

它还自动添加了 root 元素和声明到 XML 字符串。与其它库不同,输出默认已格式化以提高可读性。

对于所有非字符串字段,它会在标签上添加类型属性,例如给 age 元素添加 number 属性。这使得如果需要的话,解析 XML 字符串回 JSON 更加方便。

如果我们不需要这些属性,可以使用 U.JsonToXmlMode.REMOVE_ATTRIBUTES 选项禁用它们:

@Test
public void givenJsonString_whenConvertToXMLUsingUnderscoreJavaWithoutAttributes_thenConverted() {
    String jsonString = "{\"name\":\"John\", \"age\":20}";
    String xmlString = U.jsonToXml(jsonString, U.JsonToXmlMode.REMOVE_ATTRIBUTES);
    Assertions.assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
      "<root>\n" +
      "  <name>John</name>\n" +
      "  <age>20</age>\n" +
      "</root>", xmlString);
}

如我们所见,age 元素不再带有 number 属性。

5. 总结

在这篇文章中,我们探讨了在 Java 中将 JSON 转换为 XML 的几种方法,并通过一些示例理解了转换过程。

如往常一样,代码示例可以在 GitHub 上找到。