使用杰克逊将具有重复元素的 XML 转换为 JSON

Posted

技术标签:

【中文标题】使用杰克逊将具有重复元素的 XML 转换为 JSON【英文标题】:Convert XML with duplicate elements to JSON using jackson 【发布时间】:2012-09-07 18:28:15 【问题描述】:

我有一些 XML 格式的简单数据,我需要将其转换为 JSON,并且还能够将 JSON 转换回相同的 XML 字符串。但是我在使用现有的 jackson(2.0.6 版)库时遇到了问题。

这是一个具有类似结构的 XML 数据示例

<channels>
  <channel>A</channel>
  <channel>B</channel>
  <channel>C</channel>
</channels>

为了能够将其转换回原始 XML,我希望 JSON 看起来像这样


  "channels": 
    "channel": [
      "A",
      "B",
      "C"
    ]
  

但是杰克逊给了我

"channel":"C"

不保留根元素名称,而是创建通道数组,最后一个覆盖以前的。

查看 com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer 的源代码,我发现该库不支持此功能,但允许覆盖和更改行为。

/**
 * Method called when there is a duplicate value for a field.
 * By default we don't care, and the last value is used.
 * Can be overridden to provide alternate handling, such as throwing
 * an exception, or choosing different strategy for combining values
 * or choosing which one to keep.
 *
 * @param fieldName Name of the field for which duplicate value was found
 * @param objectNode Object node that contains values
 * @param oldValue Value that existed for the object node before newValue
 *   was added
 * @param newValue Newly added value just added to the object node
 */
protected void _handleDuplicateField(String fieldName, ObjectNode objectNode,
                                     JsonNode oldValue, JsonNode newValue)
    throws JsonProcessingException

    // By default, we don't do anything
    ;

所以我的问题是

    是否有人编写了自定义反序列化器来支持此功能?或者有其他方法可以解决这个问题。 如何保留根元素名称?

下面是一个测试示例

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
public class Test 
  public static void main(String[] args) throws Exception 
    String xml="<channels><channel>A</channel><channel>B</channel><channel>C</channel></channels>";

    XmlMapper xmlMapper = new XmlMapper();
    JsonNode node=xmlMapper.readValue(xml,JsonNode.class);
    System.out.println(node.toString());
  

【问题讨论】:

FWIW,_handleDuplicateField 不是这样做的方法——它只是一个错误处理。此外,您不能有效地使用树模型来处理这个问题——XML 数据绑定需要一些解决方法,如果没有 Java 类提供的类型信息,这些解决方法就无法应用。 我想我可能走错了方向。感谢您为我澄清这一点:) 对我来说,最好为我必须能够序列化和反序列化的少数变体创建一些 POJO,至少在杰克逊库在 2.1 版中对此提供适当支持之前。跨度> 【参考方案1】:

这里真正重要的是你的类——仅仅显示 XML 本身并不能提供足够的信息来了解发生了什么。

我怀疑您将需要 Jackson 2.1(一旦它在一两周内发布),因为它最终正确地支持“解包列表”。在此之前,只有“包装”列表才能正常工作。

【讨论】:

好的,谢谢你的回答,我会在更新版本出来时检查它。我很惊讶jackson-dataformat-xml的概述页面上没有提到这一点 对了,我忘了说我目前使用的是jackson库的2.0.6版本(jackson-dataformat-xml的2.0.5)。 同意介绍页面是不完整的——缺乏对“未包装”数组的支持是一件大事,很容易让任何期望完全兼容 JAXB 的人陷入困境。

以上是关于使用杰克逊将具有重复元素的 XML 转换为 JSON的主要内容,如果未能解决你的问题,请参考以下文章

Java - 使用杰克逊将 json 转换为复杂对象

将 XML 文件转换为具有列表的 XML 对象 [重复]

将具有重复节点的 XML 转换为 R 数据框

将父元素添加到子元素以具有一个元组(将 XML 转换为字典集合时)

XSLT:XML 第一个属性需要转换为具有第二个属性值的元素

将具有混合复杂类型元素的 XML 转换为 DataSet,以及其他 DataSet 限制