Javascript is required
踩坑避坑发布于 2026-07-28审校于 2026-08-085 分钟阅读

JSON 转 XML 遇到数组、重复同名元素与属性层级冲突的解决方案

JSON 只有对象、数组、字符串和数字,没有原生属性、命名空间或重复兄弟元素。将 JSON 转换到 XML 之前,必须决定数组如何重复元素、属性写在哪里、文本如何表达,以及命名冲突如何解决。本文讨论该映射契约。

JSON to XMLArraysAttributesSchema Conflict

一、问题概述:同样 JSON 对应多种 XML 结构

一个 items 数组可以变成重复的 item 元素,也可以包一层 items 容器;一个 id 可以是子节点,也可以是属性。如果没有输入输出契约,转换器可能会生成合规但违背接收方 Schema 的 XML。

二、最小复现:明确数组与属性的标识规则

以下约定使用 attributes 表示属性、children 表示子节点、text 表示文本;数组值会重复同名子节点。它是本文的输入契约,不代表所有工具都采用相同键名。

const input = {
  name: "order",
  attributes: { id: "ord-1" },
  children: {
    customer: { text: "Ada" },
    item: [{ attributes: { sku: "book" }, text: "1" }, { attributes: { sku: "pen" }, text: "2" }],
  },
};
// <order id="ord-1"><customer>Ada</customer><item sku="book">1</item><item sku="pen">2</item></order>

三、根因:JSON 没有同名节点和属性层级

对象键必须唯一,而 XML 允许多个同名兄弟元素;JSON 的键值也没有办法单独表达属性与文本节点。把数组索引拼到标签名会改变 XML vocabulary,把所有字段都变成子节点又可能违反对方的属性约定。

四、推荐方案:先写映射表再调用转换器

为每个对象确定元素名、属性集合、文本字段和子节点集合。数组统一采用重复元素还是容器元素;同一对象同时拥有 textchildren 时,规定是否允许混合内容。对未知字段报错或列入扩展区,不要静默改名。

五、完整代码:把约定转换成节点列表

下面的函数只建立 XML 节点模型,序列化器可以据此转义文本和属性。它刻意保留重复节点,不把数组下标写进标签名。

type XmlNode = {
  name: string;
  attributes?: Record<string, string>;
  text?: string;
  children?: XmlNode[];
};

function orderToNodes(order: { id: string; customer: string; items: Array<{ sku: string; quantity: number }> }): XmlNode {
  return {
    name: "order",
    attributes: { id: order.id },
    children: [
      { name: "customer", text: order.customer },
      ...order.items.map((item) => ({ name: "item", attributes: { sku: item.sku }, text: String(item.quantity) })),
    ],
  };
}

console.log(orderToNodes({ id: "ord-1", customer: "Ada", items: [{ sku: "book", quantity: 1 }] }));

六、常见错误方案

items[0]items[1] 直接作为标签名会让 schema 随数据长度变化;把属性和子节点同名会使接收端无法判断优先级;把空数组输出成空字符串也会混淆“没有节点”和“有一个空节点”。

七、边界条件:空数组、同名字段与顺序

空数组应按契约输出为空容器或不输出节点,不能临时猜测。多个同名元素的顺序可能有业务意义,序列化器必须稳定保留。若 JSON 同时出现属性候选和子节点候选,应在 schema 层拒绝冲突,而不是覆盖一个值。

八、如何验证输入输出

用单元素、多元素、空数组、缺失属性、空文本和包含 &<> 的值测试。断言元素名称、重复次数、属性集合、子节点顺序和转义结果;再用接收方 XSD 或示例报文验证结构,而不只比较缩进后的字符串。

九、FAQ

问:数组一定要包一层容器吗?答:不一定,取决于接收方 schema;重复同名元素是另一种合法约定。

问:同名 JSON 字段能直接生成同名 XML 节点吗?答:单个对象键不能重复,必须用数组表达多个兄弟节点。

问:属性能从字段名自动猜吗?答:不能,应使用明确的属性列表和未知字段策略。

十、总结

JSON 转 XML 的难点不是打印尖括号,而是定义数组、属性、文本和同名节点的契约。先确定元素模型与冲突策略,再生成重复节点并验证顺序、空值和转义;不要依赖转换器的默认猜测。

来源与延伸阅读

技术审校所依据的规范与权威参考资料。

相关文章

继续阅读

可打开关联的浏览器工具,使用自己的样本验证文中的处理流程。

打开关联工具