如何通过jq/yq实现XML转JSON时单个元素统一转为数组格式
问题解决方案
你之前的命令执行失败的核心原因是手动写死的字段路径不匹配嵌套结构,且没有对多层嵌套的同名def元素做递归处理,也没有兼容字段已经是数组的场景,所以会返回空数组。
最稳妥的实现方式是用jq内置的walk函数递归遍历所有JSON节点,统一处理需要强制转为数组的字段,不用手动硬编码每一层路径,能覆盖任意嵌套深度的目标元素。
可直接执行的命令
输出JSON格式
cat test.xml | xq ' walk( if type == "object" then . as $currentNode | reduce ["def", "ex", "kref"][] as $targetKey ( .; if has($targetKey) then .[$targetKey] = if ($currentNode[$targetKey] | type) == "array" then $currentNode[$targetKey] else [$currentNode[$targetKey]] end else . end ) else . end ) '
直接输出最终YAML格式(无需额外中转处理)
如果后续要直接转YAML,直接在管道后追加yq的转yaml参数即可:
cat test.xml | xq ' walk( if type == "object" then . as $currentNode | reduce ["def", "ex", "kref"][] as $targetKey ( .; if has($targetKey) then .[$targetKey] = if ($currentNode[$targetKey] | type) == "array" then $currentNode[$targetKey] else [$currentNode[$targetKey]] end else . end ) else . end ) ' | yq -y .
逻辑说明
walk函数会递归遍历转换后JSON的每一层节点,不管<def>嵌套多少层都能被覆盖,不会出现路径匹配遗漏的问题- 对每个对象节点,逐一检查是否存在
def/ex/kref三个目标字段 - 字段存在时做类型判断:如果是XML里多个同名字段转出来的原生数组,直接保留原结构;如果是单个字段转出来的对象,自动包裹为单元素数组,保证无论字段出现多少次,输出结构始终满足数组类型一致性要求
- 非目标字段完全不受影响,和默认转换的输出结构一致
执行上述命令处理你提供的示例XML,输出结果和你给出的期望JSON结构完全一致。
内容的提问来源于stack exchange,提问作者Boyd
相关产品推荐
相关产品推荐

