基于元素重新格式化分层数据的输出

reformat output of hierarchical data, based on an element

鉴于以下 json,其中包含分层数据,我需要将以下平面结构转换为父子 json 输出格式:

[{
    "ID": 1042,
    "NameID": "200",
    "Name": "related",
    "path": "1042"
}, {
    "ID": 1561,
    "NameID": "  230",
    "Name": "Patr",
    "FatherID": 1042,
    "path": "1042\/1561"
}, {
    "ID": 1370,
    "NameID": "    230",
    "Name": "Dog",
    "FatherID": 1561,
    "path": "1042\/1561\/1370"
}, {
    "ID": 1560,
    "NameID": "    230.1",
    "Name": "Ort",
    "FatherID": 1561,
    "path": "1042\/1561\/1560"
}, {
    "ID": 213,
    "NameID": "    232",
    "Name": "Jim",
    "FatherID": 1561,
    "path": "1042\/1561\/213"
}]

如何根据路径层次结构获得如下所示的输出?:

我只替换了第一个值,因为我需要证明深度可能会继续......

[
  {
    "200": "related",
    "Children": [
      {
        "  230": "Patr",
        "Children": [
          {
            "230.1": "Ort",
            "Children": [
              {
                "NameID": "Name",
                "Children": [
                  {
                    "NameID": "Name",
                    "children": [
                      {
                        "NameID": "Name"
                      },
                      {
                        "NameID": "Name"
                      }
                    ]
                  },
                  {
                    "NameID": "Name",
                    "children": [
                      {
                        "NameID": "Name"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }

下面的解决方案的关键是将平面数组转换为层次结构。我们使用 setpath 来执行此操作,如下所示:

reduce .[] as $element ({};
  setpath($element | .path | split("\/");
          $element | {NameID, Name}))

根据您的输入,结果如下:

{
  "1042": {
    "NameID": "200",
    "Name": "related",
    "1561": {
      "NameID": "  230",
      "Name": "Patr",
      "1370": {
        "NameID": "    230",
        "Name": "Dog"
      },
      "1560": {
        "NameID": "    230.1",
        "Name": "Ort"
      },
      "213": {
        "NameID": "    232",
        "Name": "Jim"
      }
    }
  }
}

现在只是一个修改的问题,可以使用以下辅助函数来完成:

def promote:
  . as $in
  | (if .NameID then {(.NameID): .Name } else {} end) as $base
  | del(.NameID) | del(.Name)
  | if length == 0 then $base
    else $base + {Children: (reduce keys_unsorted[] as $k ([]; . + [$in[$k] | promote] ))}
    end;

有了这个定义,解决方案就变成了:

reduce .[] as $element ({};
  setpath($element | .path | split("\/");
          $element | {NameID, Name}))
| promote
| .Children

输出

[
  {
    "200": "related",
    "Children": [
      {
        "  230": "Patr",
        "Children": [
          {
            "    230": "Dog"
          },
          {
            "    230.1": "Ort"
          },
          {
            "    232": "Jim"
          }
        ]
      }
    ]
  }
]