Javascript is required
错误排查发布于 2026-07-28审校于 2026-08-084 分钟阅读

XML 转 JSON:单节点与多节点的数组形状推断

XML 允许同名兄弟元素,JSON 却要在对象属性和数组之间作出选择。当 <item> 只有一个时输出对象、出现两个时输出数组,调用方就会遇到形状不稳定的问题。本文只讨论单节点/多节点的数组策略,不讨论命名空间或 XML 解析性能。

XML to JSONArraysSchemaShape Inference

一、问题概述:同一个元素会产生两种 JSON 形状

<items><item>book</item></items> 可以被转换成 {"item":"book"},而增加第二个 <item> 后又可能变成 {"item":["book","pen"]}。消费者若直接调用 map,单节点结果就会报错;若总是取下标,数组结果又可能丢掉数据。

二、最小复现:单个和多个同名节点

下面的输入已经被表示为同名 XML 节点列表;重点是投影策略,而不是某个 XML parser 的 API。

type XmlNode = { name: string; text: string };
const one: XmlNode[] = [{ name: "item", text: "book" }];
const many: XmlNode[] = [{ name: "item", text: "book" }, { name: "item", text: "pen" }];

console.log(one.length, many.length); // 1, 2
// An object-or-array converter changes shape when the count changes.

三、根因:XML 的重复元素没有天然的 JSON 约定

XML schema 可以允许 maxOccurs 大于 1,也可以只允许一次;JSON 转换器如果没有 schema,只能根据当前样本猜测。猜测还会受到空元素、混合内容和同名不同上下文的影响,因此“单个就对象”不是普遍标准。

四、方案比较:始终数组、schema 驱动与后处理

始终数组最容易让调用方编程,但会改变只含一个值时的输出契约;schema 驱动可以按 maxOccurs 生成稳定形状,却要求拿到可信 schema;后处理适合兼容旧接口,但必须记录哪些路径被归一化,不能在业务代码里到处写特判。

五、完整代码:按策略归一化同名节点

以下代码展示一个小型后处理函数。always-array 保持数组,singleton 在没有节点时返回 null、一个节点时返回值、多个节点时返回数组;生产转换应把策略放在字段 schema 中。

type XmlNode = { name: string; text: string };
type ArrayPolicy = "always-array" | "singleton";

function projectItems(nodes: XmlNode[], policy: ArrayPolicy): string[] | string | null {
  const values = nodes.filter((node) => node.name === "item").map((node) => node.text);
  if (policy === "always-array") return values;
  if (values.length === 0) return null;
  return values.length === 1 ? values[0] : values;
}

console.log(projectItems([{ name: "item", text: "book" }], "always-array")); // ["book"]
console.log(projectItems([{ name: "item", text: "book" }], "singleton")); // "book"

六、常见错误方案

只用第一条同名节点会静默丢数据;看到数组就强制取 [0] 会破坏多值字段;在没有 schema 的情况下凭字段名猜测基数,也可能把一次性元素误包装成数组。把 null、空数组和缺失节点混成同一种值,会进一步模糊契约。

七、边界条件:空元素、顺序与嵌套路径

<item/> 应该是空字符串、null 还是空对象,要由 schema 决定。同名节点的顺序可能是业务顺序,归一化时不能排序。不同父路径下的 item 也可能有不同基数,策略应绑定完整路径而不是全局标签名。

八、如何验证输出形状

分别测试零个、一个和多个节点,断言 JSON 类型、元素数量和原始顺序。再用 schema 驱动样本验证 minOccurs/maxOccurs 或等价约束,并对旧接口的后处理结果做快照;不要只检查 JSON 是否能被序列化。

九、FAQ

问:始终数组是不是最正确?答:它通常更稳定,但必须与现有 API 契约和消费者预期一致。

问:没有 XSD 能推断数组吗?答:只能根据样本做暂时策略,不能把一次观察当成长期 schema。

问:后处理会不会掩盖 parser 问题?答:会,所以应在归一化前验证节点数量和路径,失败时保留原始上下文。

十、总结

单节点/多节点导致的形状变化来自 XML 重复元素与 JSON 数组之间缺少天然映射。优先选择稳定的始终数组或可信 schema 驱动策略;必须兼容旧结果时再做集中后处理,并验证零个、一个、多个节点及顺序边界。

来源与延伸阅读

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

相关文章

继续阅读

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

打开关联工具