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

时间:2018-11-26 19:06:31

标签: json jq hierarchical-data

鉴于以下包含分层数据的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"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }

1 个答案:

答案 0 :(得分:0)

以下解决方案的关键是将平面数组转换为分层结构。我们使用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"
          }
        ]
      }
    ]
  }
]