我可以根据列表中的值输出布尔值吗?
Can I output boolean based on values in a list?
编辑:我使用@peak 提供的解决方案来执行以下操作:
$ jq -r --argjson whitelist '["role1", "role2"]' '
select(has("roles") and any(.roles[]; . == "role1" or . == "role2"))
| (reduce ."roles"[] as $r ({}; .[$r]=true)) as $roles
| [.email, .username, .given_name, .family_name, ($roles[$whitelist[]]
| . != null)]
| @csv
' users.json
添加了 select()
以过滤掉尚未入职且没有任何角色的用户,并确保输出中包含的用户至少具有一种目标角色。
场景:用户个人资料作为 JSON 文档,其中每个个人资料都有一个列表对象及其分配的角色。示例:
{
"username": "janedoe",
"roles": [
"role1",
"role4",
"role5"
]
}
实际的数据文件是一个ndjson文件,每行一个用户对象。
我只对特定角色感兴趣,例如 role1
、role3
和 role4
。我想生成格式为:
的 CSV
username,role1?,role3?,role4?
例如,
janedoe,true,false,true
我还没有弄清楚的部分是如何输出布尔值或 Y / N 以响应列表对象中的值。这是我可以在 jq
本身做的事情吗?
根据您的输入,调用:
jq -r --argjson whitelist '["role1", "role3", "role4"]' '
(["username"] + $whitelist),
[.username, ($whitelist[] as $w | .roles | index([$w]) != null)]
| @csv
'
产生:
"username","role1","role3","role4"
"janedoe",true,false,true
备注:
上面jq过滤器的倒数第二行可以缩短为:
[.username, (.roles | index($whitelist[]) != null)]
大概如果有多个用户,你只需要
header 行一次,在这种情况下,上述解决方案
需要进行调整。
使用IN/1
因为 index/1
效率不如预期,
你可能想考虑这个替代方案:
(["username"] + $whitelist),
(.roles as $roles | [.username, ($whitelist[] | IN($roles[]) )])
| @csv
使用 JSON 字典
如果角色的数量很大,那么可能会更多
构建 JSON 字典以避免重复线性查找的效率:
(reduce .roles[] as $r ({}; .[$r]=true)) as $roles
| (["username"] + $whitelist),
[.username, ($roles[$whitelist[]] != null)]
| @csv
以ndjson为输入
为了提高效率,并确保只有一个 header,您可以使用带有 -n command-line 选项的 inputs
。添加修改后的 Q 中提到的额外字段,您最终可能会得到:
jq -nr --argjson whitelist '["role1", "role2"]' '
["email", "username", "given_name", "family_name"] as $greenlist
| ($greenlist + $whitelist),
(inputs
| select(has("roles") and any(.roles[] == $whitelist[]; true))
| (reduce ."roles"[] as $r ({}; .[$r]=true)) as $roles
| [ .[$greenlist[]], ($roles[$whitelist[]] != null) ])
| @csv
' users.json
编辑:我使用@peak 提供的解决方案来执行以下操作:
$ jq -r --argjson whitelist '["role1", "role2"]' '
select(has("roles") and any(.roles[]; . == "role1" or . == "role2"))
| (reduce ."roles"[] as $r ({}; .[$r]=true)) as $roles
| [.email, .username, .given_name, .family_name, ($roles[$whitelist[]]
| . != null)]
| @csv
' users.json
添加了 select()
以过滤掉尚未入职且没有任何角色的用户,并确保输出中包含的用户至少具有一种目标角色。
场景:用户个人资料作为 JSON 文档,其中每个个人资料都有一个列表对象及其分配的角色。示例:
{
"username": "janedoe",
"roles": [
"role1",
"role4",
"role5"
]
}
实际的数据文件是一个ndjson文件,每行一个用户对象。
我只对特定角色感兴趣,例如 role1
、role3
和 role4
。我想生成格式为:
username,role1?,role3?,role4?
例如,
janedoe,true,false,true
我还没有弄清楚的部分是如何输出布尔值或 Y / N 以响应列表对象中的值。这是我可以在 jq
本身做的事情吗?
根据您的输入,调用:
jq -r --argjson whitelist '["role1", "role3", "role4"]' '
(["username"] + $whitelist),
[.username, ($whitelist[] as $w | .roles | index([$w]) != null)]
| @csv
'
产生:
"username","role1","role3","role4"
"janedoe",true,false,true
备注:
上面jq过滤器的倒数第二行可以缩短为:
[.username, (.roles | index($whitelist[]) != null)]
大概如果有多个用户,你只需要 header 行一次,在这种情况下,上述解决方案 需要进行调整。
使用IN/1
因为 index/1
效率不如预期,
你可能想考虑这个替代方案:
(["username"] + $whitelist),
(.roles as $roles | [.username, ($whitelist[] | IN($roles[]) )])
| @csv
使用 JSON 字典
如果角色的数量很大,那么可能会更多 构建 JSON 字典以避免重复线性查找的效率:
(reduce .roles[] as $r ({}; .[$r]=true)) as $roles
| (["username"] + $whitelist),
[.username, ($roles[$whitelist[]] != null)]
| @csv
以ndjson为输入
为了提高效率,并确保只有一个 header,您可以使用带有 -n command-line 选项的 inputs
。添加修改后的 Q 中提到的额外字段,您最终可能会得到:
jq -nr --argjson whitelist '["role1", "role2"]' '
["email", "username", "given_name", "family_name"] as $greenlist
| ($greenlist + $whitelist),
(inputs
| select(has("roles") and any(.roles[] == $whitelist[]; true))
| (reduce ."roles"[] as $r ({}; .[$r]=true)) as $roles
| [ .[$greenlist[]], ($roles[$whitelist[]] != null) ])
| @csv
' users.json