5

我正在使用以下代码将我的源 XML 转换为 JSON。但是,此代码会删除源 XML 中任何多次出现的子记录,并且输出 JSON 仅包含最后一个子记录。

如何让 Jackson XML 到 JSON 转换器以 JSON 格式输出所有子记录?

代码

XmlMapper xmlMapper = new XmlMapper();
Map entries = xmlMapper.readValue(new File("source.xml"), LinkedHashMap.class);
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writer().writeValueAsString(entries);
System.out.println(json);

源 XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<File>
  <NumLeases>1</NumLeases>
  <FLAG>SUCCESS</FLAG>
  <MESSAGE>Test Upload</MESSAGE>
  <Lease>
     <LeaseVersion>1</LeaseVersion>
     <F1501B>
        <NEDOCO>18738</NEDOCO>
        <NWUNIT>0004</NWUNIT>
        <NTRUSTRECORDKEY>12</NTRUSTRECORDKEY>
     </F1501B>
     <F1501B>
        <NEDOCO>18739</NEDOCO>
        <NWUNIT>0005</NWUNIT>
        <NTRUSTRECORDKEY>8</NTRUSTRECORDKEY>
     </F1501B>
  </Lease>
</File>

实际输出

{
  "NumLeases": "1",
  "FLAG": "SUCCESS",
  "MESSAGE": "Test Upload",
  "Lease": {
    "LeaseVersion": "1",
    "F1501B": {
      "NEDOCO": "18739",
      "NWUNIT": "0005",
      "NTRUSTRECORDKEY": "8"
    }
  }
}

预期产出

{
  "NumLeases": "1",
  "FLAG": "SUCCESS",
  "MESSAGE": "Test Upload",
  "Lease": {
    "LeaseVersion": "1",
    "F1501B": [
      {
        "NEDOCO": "18738",
        "NWUNIT": "0004",
        "NTRUSTRECORDKEY": "12"
      },
      {
        "NEDOCO": "18739",
        "NWUNIT": "0005",
        "NTRUSTRECORDKEY": "8"
      }
    ]
  }
}

任何帮助将不胜感激。谢谢!

4

3 回答 3

8

通过使用org.json API 将源 XML 转换为JSONObject,然后通过 Jackson API 转换为 JSON,我能够解决这个问题。

代码

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.commons.io.IOUtils;
import org.json.JSONObject;
import org.json.XML;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

...
...

try (InputStream inputStream = new FileInputStream(new File(
                "source.xml"))) {
    String xml = IOUtils.toString(inputStream);
    JSONObject jObject = XML.toJSONObject(xml);
    ObjectMapper mapper = new ObjectMapper();
    mapper.enable(SerializationFeature.INDENT_OUTPUT);
    Object json = mapper.readValue(jObject.toString(), Object.class);
    String output = mapper.writeValueAsString(json);
    System.out.println(output);
}

...
...

源 XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<File>
  <NumLeases>1</NumLeases>
  <FLAG>SUCCESS</FLAG>
  <MESSAGE>Test Upload</MESSAGE>
  <Lease>
     <LeaseVersion>1</LeaseVersion>
     <F1501B>
        <NEDOCO>18738</NEDOCO>
        <NWUNIT>0004</NWUNIT>
        <NTRUSTRECORDKEY>12</NTRUSTRECORDKEY>
     </F1501B>
     <F1501B>
        <NEDOCO>18739</NEDOCO>
        <NWUNIT>0005</NWUNIT>
        <NTRUSTRECORDKEY>8</NTRUSTRECORDKEY>
     </F1501B>
  </Lease>
</File>

输出

{
  "File" : {
    "NumLeases" : "1",
    "FLAG" : "SUCCESS",
    "MESSAGE" : "Test Upload",
    "Lease" : {
      "LeaseVersion" : "1",
      "F1501B" : [ {
        "NEDOCO" : "18738",
        "NWUNIT" : "0004",
        "NTRUSTRECORDKEY" : "12"
      }, {
        "NEDOCO" : "18739",
        "NWUNIT" : "0005",
        "NTRUSTRECORDKEY" : "8"
      } ]
    }
  }
}
于 2016-04-07T19:01:37.530 回答
0

问题是 XML 没有区分“对象”(JSON 术语,即键/值对的集合)和“数组”(没有名称的有序值序列)的概念。使用数据绑定 (POJO) 时,可以从 Java 类型确定特定 XML 元素的含义——如果 Java 属性是一个List或数组,它必须是“数组”;否则为“对象”——但是当仅告诉映射器将 XML 映射到java.util.Map没有这种区别时,默认处理将基本上考虑所有 XML 元素以指示“对象”。并且由于“对象”不能具有具有重复名称的属性,因此仅保留其中一个值(最后一个)。

没有简单的方法可以避免使用XmlMapper:您将需要某种自定义处理。

于 2016-04-05T00:11:16.010 回答
0

这可以通过更新到 Jackson 版本 2.12.x 来解决

如果使用 maven,则可以更新版本,将此属性添加到 pom.xml

<properties>
 <jackson-bom.version>2.12.4</jackson-bom.version>
</properties>

此处提供有关库改进的更多详细信息 - https://cowtowncoder.medium.com/jackson-2-12-improved-xml-b9487889a23f

于 2021-09-09T10:58:35.353 回答