Как отфильтровать пары ключей в массиве объектов (json и jq) - PullRequest
0 голосов
/ 16 апреля 2019

Это продолжение ошибки jq: «Невозможно проиндексировать строку со строкой »

Ранее я мог фильтровать записи в файле json, который имеетцелевые объекты с помощью следующей команды и фильтра:

[{
    "input": {
        "obj1": {
            "$link": "randomtext1"
        },
        "id": "a"
    }
}]

jq -r '.[] | select( any(.input[]; type=="object" and has("$link") and (.["$link"]=="randomtext1")))|.id' даст "a"

Как мне отфильтровать, если теперь ключ "$ link" и его значение "randomtext1"принадлежать массиву?

[{
    "input": {
        "obj1": [{
            "$link": "randomtext1"
        }],
        "id": "a"
    }
}]

(я все еще хочу иметь возможность найти "a" в качестве результата)

Пример .json:

[
  {
    "input": {
      "obj1": [{
        "$link": "randomtext1"
      }],
      "obj2": [{
        "$link": "randomtext2"
      }],
      "someotherobj": "123"
    },
    "id": "a"
  },
  {
    "input": {
      "obj3": {
        "$link": "randomtext1"
      },
      "obj4": {
        "$link": "randomtext2"
      }
    },
    "id": "b"
  }
]

IЯ надеюсь найти и a и b с ключевым словом randomtext1, но получил b с тем же фильтром из предыдущего случая после того, как obj1 и obj2 были «экранированы / замаскированы» скобками массива в примере файла json.

Ответы [ 2 ]

0 голосов
/ 19 апреля 2019

в качестве альтернативы вы можете рассмотреть возможность использования утилиты Unix на основе пешеходного пути jtc:

bash $ <file.json jtc -w'<id>l:<val>v[-1]<input>l[$link]:<randomtext1>' -T'{{val}}'
"a"
"b"
bash $ 

для уточнения тропы (-w):

- '<id>l:< - найдет каждое значение, помеченное id

- <val>v запомнит значение в пространство имен val

- [-1] перейти на один уровень выше найденной записи (в основном адрес родителя)

- <input>l[$link]:<randomtext1> - найдет под данной записью Json каждую запись "$link": "randomtext1" под записью "input"

, если все успешно, тогда интерполяция происходит в (-T) и интерполированное ранее запомненное значение.

тот же запрос будет работать и с вашими данными в предыдущем сообщении.

0 голосов
/ 16 апреля 2019

Просто добавьте «или», чтобы охватить новую возможность:

.[]
| select( any(.input[];
              (type=="object" and (has("$link") and (.["$link"]=="randomtext1")))
              or (type=="array" and any(.[];
                                        type == "object" and (has("$link") and (.["$link"]=="randomtext1")))) ))
|.id

... или более наглядно:

def relevant($txt):
  type == "object" and has("$link") and (.["$link"]==$txt);

.[]
| select( any(.input[];
              relevant("randomtext1")
              or (type=="array" and any(.[]; relevant("randomtext1"))) ))
|.id
...