将 JSON 类别树转换为数据库表

Posted

技术标签:

【中文标题】将 JSON 类别树转换为数据库表【英文标题】:Convert JSON categories tree to database table 【发布时间】: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 中引入的。

【问题讨论】:

【参考方案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!

【讨论】:

以上是关于将 JSON 类别树转换为数据库表的主要内容,如果未能解决你的问题,请参考以下文章

如何将分层表转换为json

如何将熊猫数据透视表转换为 JSON [重复]

将sql表数据转换为json

将多个 JSON 数据转换为 HTML 表 [重复]

将 Google BigQuery 中一个表中的 XML 数据转换为同一表中另一列中的 JSON 数据

将 Pandas Dataframe 转换为表记录的嵌套 JSON