You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用jq改造树形JSON:上移单元素列表项、删除空项

需求:用jq处理树形JSON

核心目标

对类文件/文件夹结构的树形JSON执行两类转换:

  • 将仅含单个子项的节点从叶子层级上移(删除中间节点,把子项直接放到原父节点下)
  • 删除仅包含基础字段的空节点

结构说明

树形结构的组成规则:

  • 可选的.item[]数组:用于存储子节点
  • 必选的.name字段:节点名称
  • 可选的.description字段:节点描述
  • 若节点存在除上述字段外的其他额外字段,则该节点不可被删除或合并

示例场景解析

  • objects/:带有"root f"注释,保留原结构
  • external:无额外字段,但包含2个子项,不执行上移操作
  • external/buuu和external/biii:含额外字段,保留原节点不做处理
  • objects/afolder/methods下的empty和empty2:仅包含name、description或空item数组,属于待删除的空项
  • objects/afolder/methods/partner1/operand:仅含单个子项,将子项whetever4上移至partner1下,删除operand节点
  • objects/afolder/methods/partner2/operand2:仅含单个子项,将子项whatever3上移至partner2下(与operandx同级),删除operand2节点

转换规则

  1. jq表达式仅可引用item、name、description字段,不可指定自定义字段(如beep1、keep1等)
  2. 保留原有字段的顺序
  3. 上移子项时,需放置在原父节点所在的位置
  4. 仅当节点下仅有单个子项时才执行上移操作,多子项时不处理

输入示例JSON

{
    "item": [
        {
            "name": "objects",
            "description": "root f",
            "item": [
                {
                    "name": "external",
                    "item": [
                        {
                            "name": "buuu",
                            "keep1": {}
                        },
                        {
                            "name": "biii",
                            "keep1": {}
                        }
                    ],
                    "description": "Whatever comment."
                },
                {
                    "name": "afolder",
                    "item": [
                        {
                            "name": "methods",
                            "item": [
                                {
                                    "name": "blaaa",
                                    "keep1": {}
                                },
                                {
                                    "name": "empty",
                                    "description": "Whatever2.",
                                    "item": []
                                },
                                {
                                    "name": "partner1",
                                    "item": [
                                        {
                                            "name": "operand",
                                            "item": [
                                                {
                                                    "name": "whetever4",
                                                    "beep1": { },
                                                    "beep2": []
                                                }
                                            ]
                                        }
                                    ]
                                },
                                {
                                    "name": "empty2",
                                    "description": "Whatever3."
                                },
                                {
                                    "name": "partner2",
                                    "item": [
                                        {
                                            "name": "operandx",
                                            "beep2": []
                                        },
                                        {
                                            "name": "operand2",
                                            "item": [
                                                {
                                                    "name": "whatever3",
                                                    "beep1": { },
                                                    "beep2": []
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

预期输出示例JSON

{
    "item": [
        {
            "name": "objects",
            "description": "root f",
            "item": [
                {
                    "name": "external",
                    "item": [
                        {
                            "name": "buuu",
                            "keep1": {}
                        },
                        {
                            "name": "biii",
                            "keep1": {}
                        }
                    ],
                    "description": "Whatever comment."
                },
                {
                    "name": "afolder",
                    "item": [
                        {
                            "name": "methods",
                            "item": [
                                {
                                    "name": "blaaa",
                                    "keep1": {}
                                },
                                {
                                    "name": "partner1",
                                    "item": [
                                        {
                                            "name": "whetever4",
                                            "beep1": { },
                                            "beep2": []
                                        }
                                    ]
                                },
                                {
                                    "name": "partner2",
                                    "item": [
                                        {
                                            "name": "operandx",
                                            "beep2": []
                                        },
                                        {
                                            "name": "whatever3",
                                            "beep1": { },
                                            "beep2": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

jq解决方案

使用递归jq表达式实现转换,逻辑分为清理空节点、合并单子项节点两步:

def clean:
  # 过滤空节点:保留有额外字段或非空子项的节点
  select(
    (keys - ["name", "description", "item"] | length > 0) or
    (.item // [] | length > 0)
  ) |
  # 递归处理子项,合并符合条件的单节点
  (.item // []) |= (
    map(clean) |
    map(
      # 检查是否可合并:无额外字段且仅含单个子项
      if (keys - ["name", "description", "item"] | length == 0) and (.item | length == 1)
      then .item[0]  # 用子项替换当前节点,实现上移
      else .
      end
    )
  );

clean

使用方法

将上述表达式保存为clean-tree.jq,执行以下命令:

jq -f clean-tree.jq input.json > output.json

逻辑说明

  1. 递归清理空节点:通过select语句过滤掉仅含基础字段且无有效子项的节点
  2. 合并单子项节点:遍历子项时,判断节点是否无额外字段且仅有一个子项,若是则用子项替换当前节点,完成层级上移
  3. 保留字段顺序:jq默认保留原有字段顺序,无需额外处理

内容的提问来源于stack exchange,提问作者Tamás Horváth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 07:17:05