【问题标题】:Convert JSON categories tree to database table将 JSON 类别树转换为数据库表
【发布时间】:2018-04-04 10:14:44
【问题描述】:

假设我有一个像这样的 JSON 文件的类别树:

[
  {
    "id": "1",
    "text": "engine",
    "children": [
      {
        "id": "2",
        "text": "exhaust",
        "children": []
      },
      {
        "id": "3",
        "text": "cooling",
        "children": [
          {
            "id": "4",
            "text": "cooling fan",
            "children": []
          },
          {
            "id": "5",
            "text": "water pump",
            "children": []
          }
        ]
      }
    ]
  },
  {
    "id": "6",
    "text": "frame",
    "children": [
      {
        "id": "7",
        "text": "wheels",
        "children": []
      },
      {
        "id": "8",
        "text": "brakes",
        "children": [
          {
            "id": "9",
            "text": "brake calipers",
            "children": []
          }
        ]
      },
      {
        "id": "10",
        "text": "cables",
        "children": []
      }
    ]
  }
]

我怎样才能把它转换成这个平面表?

id  parent_id   text
1   NULL        engine
2   1           exhaust
3   1           cooling
4   3           cooling fan
5   3           water pump
6   NULL        frame
7   6           wheels
8   6           brakes
9   8           brake calipers
10  6           cables

我发现了类似的问题和倒置的问题(从表格到 JSON),但我无法用 jq 及其@tsv 过滤器弄清楚。我还注意到答案中不经常引用“扁平化”过滤器(虽然它看起来正是我需要的工具),但这可能是因为它是最近在最新版本的 jq 中引入的。

【问题讨论】:

    标签: json csv recursion jq flatten


    【解决方案1】:

    这是另一个使用 jq 的 recurse 内置的解决方案:

      ["id","parent_id","text"]
    , (
          .[]
        | recurse(.id as $p| .children[] | .parent=$p )
        | [.id, .parent, .text]
      )
    | @tsv 
    

    样本运行(假设过滤器在filter.jq 中,样本数据在data.json 中)

    $ jq -Mr -f filter.jq data.json
    id  parent_id   text
    1       engine
    2   1   exhaust
    3   1   cooling
    4   3   cooling fan
    5   3   water pump
    6       frame
    7   6   wheels
    8   6   brakes
    9   8   brake calipers
    10  6   cables
    

    Try it online!

    【讨论】:

    • 太棒了!我现在可以在 curl 之后直接使用 curl ... | jq -Mr '(.[] | recurse(.id as $p| .children[] | .parent=$p) | [.id, .parent, .text]) | @tsv'
    【解决方案2】:

    这里的关键是定义一个递归函数,像这样:

    def children($parent_id):
      .id as $id
      | [$id, $parent_id, .text],
        (.children[] | children($id)) ;
    

    使用您的数据,过滤器:

    .[]
    | children("NULL")
    | @tsv
    

    产生如下所示的制表符分隔值。现在可以轻松添加标题、根据需要转换为固定宽度格式等。

    1   NULL    engine
    2   1   exhaust
    3   1   cooling
    4   3   cooling fan
    5   3   water pump
    6   NULL    frame
    7   6   wheels
    8   6   brakes
    9   8   brake calipers
    10  6   cables
    

    【讨论】:

    • 非常感谢您的回答!最后我选择了jq170727的应用方案,因为它使用了jq内置的递归函数。
    【解决方案3】:

    这是一个使用递归函数的解决方案:

    def details($parent):
       [.id, $parent, .text],                   # details for current node
       (.id as $p | .children[] | details($p))  # details for children
    ;
    
      ["id","parent_id","text"]                 # header
    , (.[] | details(null))                     # details
    | @tsv                                      # convert to tsv
    

    样本运行(假设过滤器位于filter.jq 中,样本数据位于data.json 中)

    $ jq -Mr -f filter.jq data.json 
    id  parent_id   text
    1       engine
    2   1   exhaust
    3   1   cooling
    4   3   cooling fan
    5   3   water pump
    6       frame
    7   6   wheels
    8   6   brakes
    9   8   brake calipers
    10  6   cables
    

    Try it online!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多