Выберите объекты на основе значения переменной в объекте, используя jq

236

У меня есть следующий файл JSON:

{
    "FOO": {
        "name": "Donald",
        "location": "Stockholm"
    },
    "BAR": {
        "name": "Walt",
        "location": "Stockholm"
    },
    "BAZ": {
        "name": "Jack",
        "location": "Whereever"
    }
}

Я использую jq и хочу получить элементы «name» для объектов, где «location» - «Stockholm».

Я знаю, что могу получить все имена

cat json | jq .[] | jq ."name"
"Jack"
"Walt"
"Donald"

Но я не могу понять, как печатать только определенные объекты, учитывая значение вложенной клавиши (здесь "location" : "Stockholm").

Даниил
источник

Ответы:

341

Адаптированный из этого поста Обработка JSON с помощью jq , вы можете использовать вот select(bool)так:

$ jq '.[] | select(.location=="Stockholm")' json
{
  "location": "Stockholm",
  "name": "Walt"
}
{
  "location": "Stockholm",
  "name": "Donald"
}
Даниил
источник
30
Как бы я получил родительский «FOO», «BAR», «BAZ»?
спазм
184

Чтобы получить поток только имен:

$ jq '.[] | select(.location=="Stockholm") | .name' json

производит:

"Donald"
"Walt"

Чтобы получить поток соответствующих пар (имя ключа, атрибут «имя»), рассмотрим:

$ jq -c 'to_entries[]
        | select (.value.location == "Stockholm")
        | [.key, .value.name]' json

Вывод:

["FOO","Donald"]
["BAR","Walt"]
вершина горы
источник
Он хочет, чтобы весь объект основывался на местоположении: «Я не могу понять, как печатать только определенные объекты, учитывая значение вложенной клавиши»
Fo.
2
Тебе не нужен канал после выбора: $ jq '. [] | выберите (.location == "Стокгольм"). name 'json
Deepak
Создание nameключа переменного (использовать функцию оболочки с в $1качестве параметра) не работает: termux-contact-list |jq -r '.[] | select(.name=="$1")|.number'. Я называю это как cool_fn Name1. Тем не менее, это работает:termux-contact-list |jq -r '.[] | select(.name=="Name1")|.number'
Тимо
Вот решение, если вам нравится переменная.
Тимо
27

У меня был похожий вопрос: что если вы хотите вернуть исходный формат объекта (с именами ключей, например, FOO, BAR)?

Jq предоставляет to_entriesи from_entriesдля преобразования между объектами и массивами пары ключ-значение. Что наряду с mapизбранным

Эти функции конвертируют между объектом и массивом пар ключ-значение. Если to_entries передается объект, то для каждой записи k: v во входном файле выходной массив включает в себя {"key": k, "value": v}.

from_entries выполняет обратное преобразование, а with_entries (foo) является сокращением для to_entries | карта (foo) | from_entries, полезно для выполнения некоторых операций со всеми ключами и значениями объекта. from_entries принимает ключ, ключ, имя, имя, значение и значение в качестве ключей.

jq15 < json 'to_entries | map(select(.value.location=="Stockholm")) | from_entries'

{
  "FOO": {
    "name": "Donald",
    "location": "Stockholm"
  },
  "BAR": {
    "name": "Walt",
    "location": "Stockholm"
  }
}

Используя with_entriesсокращение, это становится:

jq15 < json 'with_entries(select(.value.location=="Stockholm"))'
{
  "FOO": {
    "name": "Donald",
    "location": "Stockholm"
  },
  "BAR": {
    "name": "Walt",
    "location": "Stockholm"
  }
}
Spazm
источник
1
Одна вещь, которая постоянно кусает меня, это то, что вы должны помнить, что при использовании with_entries()вы обычно хотите также использовать .valueв selectпредложении. Это потому, что to_entriesмакрос преобразует данные записи в .keyи .valueпары, что также происходит с with_entries.
Яакко