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

能否使用jq将路径式JSON转换为带ID与路径的嵌套树形结构?

使用jq将扁平JSON转换为带ID和路径的嵌套树形结构

原始输入数据

首先修正原始JSON的格式问题(Key/Value需加双引号):

[ 
   {"Key": "fruits/red/apple", "Value": "Red apples"}, 
   {"Key":"fruits/green/lime", "Value": "Green Limes"}, 
   {"Key": "fruits/blue/berries/blueberry", "Value": "Blue Berries"}, 
   {"Key": "vegetables/red/tomato", "Value": "Red Tomatoes"}, 
   {"Key": "vegetables/green/cucumber", "Value": "Green Cucumbers"} 
]

目标嵌套树形结构

{
  "fruits": {
    "id": 1,
    "name": "fruits",
    "children": [
       { 
          "id": 2, 
          "name": "red", 
          "path": "1.2", 
          "children": [ { "id": 3, "name": "apple", "path": "1.2.3", "description": "Red apples" } ]
       },
       { 
          "id": 4, 
          "name": "green",
          "path": "1.4", 
          "children": [ {"id": 5, "name": "lime", "path": "1.4.5", "description": "Green Limes"} ]
       },
       { 
          "id": 6, 
          "name": "blue", 
          "path": "1.6", 
          "children": [ {"id": 7, "name": "berries", "path": "1.6.7", "children": [{ "id": 8, "name": "blueberry", "path": "1.6.7.8", "description": "Blue Berries" }] } ] 
       } 
    ]
  },
  "vegetables": {
    "id": 9,
    "name": "vegetables",
    "children": [
      {
        "id": 10,
        "name": "red",
        "path": "9.10",
        "children": [ {"id": 11, "name": "tomato", "path": "9.10.11", "description": "Red Tomatoes"} ]
      },
      {
        "id": 12,
        "name": "green",
        "path": "9.12",
        "children": [ {"id": 13, "name": "cucumber", "path": "9.12.13", "description": "Green Cucumbers"} ]
      }
    ]
  }
}

jq实现代码

# 初始化全局可变计数器
[0] as $counter
# 定义递归构建节点的核心函数
| def build_node(path_components, parent_path, description):
    $counter[0] += 1
    | . as $id
    | {
        "id": $id,
        "name": path_components[0],
        "path": (parent_path + ($id | tostring)) | if parent_path == "" then . else .[1:] end
      }
    | if path_components | length > 1 then
        . + { "children": [build_node(path_components[1:], parent_path + "." + ($id | tostring), description)] }
      else
        . + { "description": description }
      end;

# 遍历输入项,逐步构建嵌套结构
reduce .[] as $item ({};
    ($item.Key | split("/")) as $parts
    | $item.Value as $desc
    | # 先确保所有父节点存在
      reduce $parts[0:-1] as $part (.;
        .[$part] //= build_node([$part], "", null)
      )
    | # 构建完整路径的节点并插入结果
      setpath($parts; build_node($parts; "", $desc))
)

代码逻辑说明

  • 全局计数器:用数组[0]实现可变计数器,每次创建节点时自增,保证ID全局唯一且连续。
  • 递归节点构建:
    • build_node函数接收路径片段、父路径、描述三个参数,每次调用生成唯一ID。
    • 根据路径片段长度判断是否为叶子节点:非叶子节点递归生成子节点,叶子节点添加描述字段。
    • 路径拼接:根节点路径直接用ID,子节点路径为父路径.ID格式,确保层级关系清晰。
  • reduce遍历处理:
    • 拆分每个输入项的Key为路径片段,先构建所有中间父节点(比如fruits/red/apple先确保fruits和red节点存在)。
    • 最后用setpath将完整路径的节点插入结果结构,自动合并已存在的父节点。

注意事项

  • 原始输入必须是合法JSON,所有键名和字符串值需用双引号包裹。
  • 路径字段处理为字符串类型(JSON不支持多级数字格式的路径),可根据需求调整格式。
  • 计数器从1开始自增,所有节点ID连续不重复。

内容的提问来源于stack exchange,提问作者Siva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:31:01