我可以根据列表中的值输出布尔值吗?

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文件,每行一个用户对象。

我只对特定角色感兴趣,例如 role1role3role4。我想生成格式为:

的 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

备注:

  1. 上面jq过滤器的倒数第二行可以缩短为:

    [.username, (.roles | index($whitelist[]) != null)]

  2. 大概如果有多个用户,你只需要 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