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

如何用JQ将多层嵌套树形JSON转换为含路径的CSV?

问题描述

我有如下树形结构的PDF书签:

Content
  Author 1
    Piece 1
    Piece 2
  Author 2
    Piece 3
    Piece 4
      Movement 1
      Movement 2
      Movement 3
    Piece 5

通过qpdf可将其格式化为如下JSON:

{
  "version": 2,
  "parameters": {
    "decodelevel": "generalized"
  },
  "outlines": [
    {
      "dest": [
        "4 0 R",
        "/Fit"
      ],
      "destpageposfrom1": 1,
      "kids": [
        {
          "dest": [
            "10 0 R",
            "/Fit"
          ],
          "destpageposfrom1": 2,
          "kids": [
            {
              "dest": [
                "10 0 R",
                "/Fit"
              ],
              "destpageposfrom1": 2,
              "kids": [],
              "object": "177 0 R",
              "open": true,
              "title": "Piece 1"
            },
            {
              "dest": [
                "15 0 R",
                "/Fit"
              ],
              "destpageposfrom1": 3,
              "kids": [],
              "object": "178 0 R",
              "open": true,
              "title": "Piece 2"
            }
          ],
          "object": "176 0 R",
          "open": true,
          "title": "Author 1"
        },
        {
          "dest": [
            "38 0 R",
            "/Fit"
          ],
          "destpageposfrom1": 4,
          "kids": [
            {
              "dest": [
                "38 0 R",
                "/Fit"
              ],
              "destpageposfrom1": 4,
              "kids": [],
              "object": "180 0 R",
              "open": true,
              "title": "Piece 3"
            },
            {
              "dest": [
                "45 0 R",
                "/Fit"
              ],
              "destpageposfrom1": 5,
              "kids": [
                {
                  "dest": [
                    "45 0 R",
                    "/Fit"
                  ],
                  "destpageposfrom1": 5,
                  "kids": [],
                  "object": "182 0 R",
                  "open": true,
                  "title": "Movement 1"
                },
                {
                  "dest": [
                    "53 0 R",
                    "/Fit"
                  ],
                  "destpageposfrom1": 6,
                  "kids": [],
                  "object": "183 0 R",
                  "open": true,
                  "title": "Movement 2"
                },
                {
                  "dest": [
                    "58 0 R",
                    "/Fit"
                  ],
                  "destpageposfrom1": 7,
                  "kids": [],
                  "object": "184 0 R",
                  "open": true,
                  "title": "Movement 3"
                }
              ],
              "object": "181 0 R",
              "open": true,
              "title": "Piece 4"
            },
            {
              "dest": [
                "79 0 R",
                "/Fit"
              ],
              "destpageposfrom1": 8,
              "kids": [],
              "object": "185 0 R",
              "open": true,
              "title": "Piece 5"
            }
          ],
          "object": "179 0 R",
          "open": true,
          "title": "Author 2"
        }
      ],
      "object": "175 0 R",
      "open": true,
      "title": "Contents"
    }
  ]
}

需要生成CSV文件,保留每个分支的最后一个title,同时记录到达该节点的完整路径及其目标页码,格式如下:

Piece 1;Author 1;Content;2
Piece 2;Author 1;Content;3
Piece 3;Author 2;Content;4
Movement 1;Piece 4;Author 2;Content;5
Movement 2;Piece 4;Author 2;Content;6
Movement 3;Piece 4;Author 2;Content;7
Piece 5;Author 2;Content;8
JQ解决方案

可以使用以下JQ命令处理上述JSON,直接生成目标格式的CSV:

jq -r 'def walk_path($path):
  .title as $title
  | ($path + [$title]) as $new_path
  | if .kids | length == 0 then
      ($new_path | reverse | join(";")) + ";" + (.destpageposfrom1 | tostring)
    else
      .kids[] | walk_path($new_path)
    end;
.outlines[] | walk_path([])' input.json

逻辑说明:

  1. 自定义递归函数walk_path($path):
    • 把当前节点的title加入到传入的路径数组中,生成新路径$new_path
    • 若当前节点没有子节点(.kids数组长度为0),则将路径反转后用;拼接,再追加页码,输出一行结果
    • 若当前节点有子节点,则递归处理每个子节点,传递更新后的路径数组
  2. 主执行逻辑:从outlines数组的根节点开始调用递归函数,初始路径为空数组。

执行命令后,输出结果将完全匹配期望的CSV格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 02:22:03