我有以下json:
[
{"id": "1", "type": "folder", "title": "folder-1"},
{"id": "2", "type": "folder", "title": "folder-2"},
{"id": "3", "type": "item", "title": "item-1", "folder": "1"},
{"id": "4", "type": "item", "title": "item-2", "folder": "2"},
{"id": "5", "type": "item", "title": "item-3"}
]
基本上,我需要使用jq生成此输出,这类似于sql join的结果:
[
{"type": "item", "title": "item-1", "folder": "folder-1"},
{"type": "item", "title": "item-2", "folder": "folder-2"},
{"type": "item", "title": "item-3"}
]
有什么想法吗?
答案 0 :(得分:1)
试试这个过滤器:
map(
(select(.type=="item") | { key: .folder, value: { type, title } }),
(select(.type=="folder") | { key: .id, value: { folder: .title } })
)
| group_by(.key)
| map(
(map(select(.key != null) | .value) | add)
// map(.value)[]
)
你必须将其分解为步骤。
获取项目和文件夹,并为每个项目和文件夹获取您感兴趣的值,并为其指定一个与之关联的密钥。
map(
(select(.type=="item") | { key: .folder, value: { type, title } }),
(select(.type=="folder") | { key: .id, value: { folder: .title } })
)
按键分组
| group_by(.key)
然后组合具有键(文件夹)的值和其他值
| map(
(map(select(.key != null) | .value) | add)
// map(.value)[]
)
答案 1 :(得分:0)
jq 'map(select(has("folder") or (.["title"] | startswith("item"))) | del(.id))' sample_file
输出:
[
{
"type": "item",
"title": "item-1",
"folder": "1"
},
{
"type": "item",
"title": "item-2",
"folder": "2"
},
{
"type": "item",
"title": "item-3"
}
]
答案 2 :(得分:0)
这是另一种解决方案,它将数据分成两个对象$folders
和$items
,然后构建所需的结果。
(
reduce map(select(.type == "folder"))[] as $f (
{}
; .[$f.id] = $f
)
) as $folders
| (
reduce map(select(.type == "item"))[] as $i (
{}
; .[$i.id] = $i
)
) as $items
| [
$items[]
| {type, title, folder}
| if .folder == null then del(.folder) else .folder = $folders[.folder].title end
]
如果您的jq版本有INDEX/2
def INDEX(stream; idx_expr):
reduce stream as $row ({};
.[$row|idx_expr|
if type != "string" then tojson
else .
end] |= $row);
这可以简化为
INDEX(.[] | select(.type == "folder"); .id) as $folders
| INDEX(.[] | select(.type == "item"); .id) as $items
| [
$items[]
| {type, title, folder}
| if .folder == null then del(.folder) else .folder = $folders[.folder].title end
]