jq での Cannot iterate over null への対処

json を jq で処理しているときに、期待しているキーがなくエラーになることがよくある。そのときの対処方法のメモ。

例えば、以下のコマンドを実行すると途中でエラーになる。

$ kubectl get clusterrole -o json | jq -r '.items[].rules[].apiGroups[]'
cert-manager.io
acme.cert-manager.io
cert-manager.io
acme.cert-manager.io

(省略)

authorization.k8s.io
rbac.authorization.k8s.io
*
jq: error (at <stdin>:11356): Cannot iterate over null (null)

これは nonResourceURLs では apiGroups というキーがなくnull が返されているのに []イテレーションしようとしているため。

対処方法 1

簡単な方法として []? とすることで null を無視できる。

$ kubectl get clusterrole -o json | jq -r '.items[].rules[].apiGroups[]?'
cert-manager.io
acme.cert-manager.io
cert-manager.io
acme.cert-manager.io

(省略)

対処方法 2

目的のキーがあるかをチェックしてそれだけを select する。

$ kubectl get clusterrole -o json | jq -r '.items[].rules[] | select(has("apiGroups")) | .apiGroups[]'
cert-manager.io
acme.cert-manager.io
cert-manager.io
acme.cert-manager.io

(省略)

map(x)[.[] | x] と同じなので、以下のようにも記載できる。

$ kubectl get clusterrole -o json | jq -r '.items[].rules | map(select(has("apiGroups"))) | .[].apiGroups[]'
cert-manager.io
acme.cert-manager.io
cert-manager.io
acme.cert-manager.io

(省略)

参考リンク