jq - выбрать объекты с заданным именем ключа

У меня есть произвольная структура с множеством уровней и т. Д. Мне нужно выбрать все объекты, содержащие ключ с именем updateDate. Как мне это сделать с jq? Я придумал один способ, но он также вызывает ошибки с недопустимыми типами данных, когда посещает лист, который мне нужно найти с помощью grep:

jq 'recurse(.[]) | has("updateDate")' | grep -Fv error

Я действительно не понимаю, как также проверять типы или листья, и подозреваю, что есть более простой способ добиться того, чего я хочу?


person Yuri Geinish    schedule 24.04.2014    source источник


Ответы (3)


В версии 1.4 вы можете просто:

jq '..|.updateDate?'

Если вы застряли на 1.3, вы можете использовать более длинную программу, например:

jq 'recurse(if type == "array" or type = "object" then .[] else empty end) | if type == "object" then .updateDate else empty end'
person user2259432    schedule 19.06.2014
comment
Это приведет к ошибке, если структура включает массивы. Я думаю, добавление |objects| в середине исправляет. - person Tgr; 26.09.2017
comment
Обратите внимание, если вы хотите отфильтровать пустые массивы, вы можете следовать stackoverflow.com/a/26196653/308851 jq '..|.updateDate?|select(length>0)' - person chx; 12.06.2019

Не проверено: как насчет jq 'recurse(.[]?) | objects | has("updateDate")'?

person hobbs    schedule 19.06.2014
comment
рекурсивный (. []?) | объекты | выберите (имеет (а)) - person Eric Hartford; 08.07.2014

Принятый ответ также дает null для каждого объекта, не имеющего ключа.

Для меня сработало:

jq '..|objects|.updateDate//empty'

Часть .updateDate//empty означает: если .updateDate равно null (или false), полностью пропустить его.

Это, конечно, не сработает, если вы ожидаете, что ваш ключ будет иметь значения false или null. В этом случае используйте это:

jq '..|objects|select(has("updateDate"))|.updateDate'
person Juan Campa    schedule 07.12.2018