Seleziona gli oggetti in base al valore della variabile nell'oggetto usando jq


236

Ho il seguente file json:

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

Sto usando jq e voglio ottenere gli elementi "name" degli oggetti in cui "location" è "Stockholm".

So di poter ottenere tutti i nomi

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

Ma non riesco a capire come stampare solo determinati oggetti, dato il valore di una sottochiave (qui "location" : "Stockholm").

Risposte:


341

Adattato da questo post su Processing JSON con jq , puoi usare il seguente select(bool):

$ jq '.[] | select(.location=="Stockholm")' json
{
  "location": "Stockholm",
  "name": "Walt"
}
{
  "location": "Stockholm",
  "name": "Donald"
}

30
Come otterrei il genitore "FOO", "BAR", "BAZ"?
spazm

184

Per ottenere un flusso di soli nomi:

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

produce:

"Donald"
"Walt"

Per ottenere un flusso di coppie corrispondenti (nome chiave, attributo "nome"), considerare:

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

Produzione:

["FOO","Donald"]
["BAR","Walt"]

Vuole l'intero oggetto in base alla posizione: "Non riesco a capire come stampare solo determinati oggetti, dato il valore di una sottochiave"
Fo.

2
Non è necessario il pipe dopo la selezione: $ jq '. [] | seleziona (.location == "Stoccolma"). name 'json
Deepak

Rendendo la namevariabile chiave (usare una funzione di shell con $1come parametro) non funziona: termux-contact-list |jq -r '.[] | select(.name=="$1")|.number'. Lo chiamo così cool_fn Name1. Tuttavia, questo funziona:termux-contact-list |jq -r '.[] | select(.name=="Name1")|.number'
Timo

Ecco la soluzione se ti piace variabile.
Timo,

27

Avevo una domanda simile analoga: che cosa succede se si desidera ripristinare il formato originale dell'oggetto (con nomi di chiave, ad esempio FOO, BAR)?

Jq fornisce to_entriese from_entriesper convertire tra oggetti e matrici coppia chiave-valore. Che insieme a maptutto il selezionare

Queste funzioni vengono convertite tra un oggetto e un array di coppie chiave-valore. Se to_entries viene passato un oggetto, quindi per ogni voce k: v nell'input, l'array di output include {"key": k, "value": v}.

from_entries fa la conversione opposta, e with_entries (foo) è una scorciatoia per to_entries | mappa (foo) | from_entries, utile per eseguire alcune operazioni su tutte le chiavi e i valori di un oggetto. from_entries accetta chiave, chiave, nome, nome, valore e valore come chiavi.

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

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

Usando la with_entriesscorciatoia, questo diventa:

jq15 < json 'with_entries(select(.value.location=="Stockholm"))'
{
  "FOO": {
    "name": "Donald",
    "location": "Stockholm"
  },
  "BAR": {
    "name": "Walt",
    "location": "Stockholm"
  }
}

1
Una cosa che mi morde è che devi ricordare che quando usi with_entries(), di solito vuoi anche usare .valuenella selectclausola. Questo perché la to_entriesmacro converte le voci fornite .keye le .valuecoppie, cosa che succede anche con with_entries.
Jaakko,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.