将JSON类别树转换为数据库表
假设我有一个类似于JSON文件的类别树:将JSON类别树转换为数据库表,json,csv,recursion,jq,flatten,Json,Csv,Recursion,Jq,Flatten,假设我有一个类似于JSON文件的类别树: [ { "id": "1", "text": "engine", "children": [ { "id": "2", "text": "exhaust", "children": [] }, { "id": "3", "text": "cooling", "children": [
[
{
"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中引入了。这里的关键是定义递归函数,如下所示:
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
这里的关键是定义递归函数,如下所示:
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
下面是一个使用递归函数的解决方案:
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
中)
以下是一个使用递归函数的解决方案:
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内置的解决方案: 示例运行(假设过滤器在
filter.jq
中,样本数据在data.json
中)
这里是另一个使用jq内置的解决方案: 示例运行(假设过滤器在
filter.jq
中,样本数据在data.json
中)
太棒了!我现在可以在卷曲后直接用卷曲管…|jq-Mr'([]|递归(.id为$p |.children[]|.parent=$p)|[.id,.parent,.text])@tsv'Brilliant!我现在可以在卷曲后直接用卷曲管…|jq-Mr'([]| recurse(.id为$p |.children[]|.parent=$p)|[.id,.parent,.text])@tsv'非常感谢您的回答!最后,我选择了jq170727的应用解决方案,因为它使用了jq内置的递归函数。非常感谢您的回答!最后,我选择了应用jq170727的解决方案,因为它使用了内置于jq的递归函数。