Pilih objek berdasarkan nilai variabel dalam objek menggunakan jq

236

Saya memiliki file json berikut:

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

Saya menggunakan jq dan ingin mendapatkan "nama" elemen dari objek di mana 'lokasi' adalah 'Stockholm'.

Saya tahu saya bisa mendapatkan semua nama dengan

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

Tapi saya tidak tahu bagaimana cara mencetak hanya objek-objek tertentu, mengingat nilai sub-kunci (di sini "location" : "Stockholm").

Daniel
sumber

Jawaban:

341

Diadaptasi dari pos ini pada Memproses JSON dengan jq , Anda dapat menggunakan yang select(bool)seperti ini:

$ jq '.[] | select(.location=="Stockholm")' json
{
  "location": "Stockholm",
  "name": "Walt"
}
{
  "location": "Stockholm",
  "name": "Donald"
}
Daniel
sumber
30
Bagaimana saya mendapatkan orangtua 'FOO', 'BAR', 'BAZ'?
spazm
184

Untuk memperoleh aliran nama saja:

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

menghasilkan:

"Donald"
"Walt"

Untuk mendapatkan aliran pasangan (nama kunci, "nama" atribut) yang sesuai, pertimbangkan:

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

Keluaran:

["FOO","Donald"]
["BAR","Walt"]
puncak
sumber
Dia ingin seluruh objek berdasarkan lokasi: "Saya tidak tahu bagaimana cara mencetak hanya objek tertentu, mengingat nilai sub kunci"
Fo.
2
Anda tidak perlu pipa setelah pemilihan: $ jq '. [] | pilih (.lokasi == "Stockholm"). nama 'json
Deepak
Membuat namevariabel kunci (menggunakan fungsi shell dengan $1sebagai parameter) tidak bekerja: termux-contact-list |jq -r '.[] | select(.name=="$1")|.number'. Saya menyebutnya seperti cool_fn Name1. Namun, ini bekerja:termux-contact-list |jq -r '.[] | select(.name=="Name1")|.number'
Timo
Ini solusinya jika Anda suka variabel.
Timo
27

Saya memiliki pertanyaan terkait yang serupa: Bagaimana jika Anda ingin format objek asli kembali (dengan nama kunci, misalnya FOO, BAR)?

Jq menyediakan to_entriesdan from_entriesuntuk mengkonversi antara objek dan array pasangan kunci-nilai. Itu bersama dengan mapsekitar pilih

Fungsi-fungsi ini mengkonversi antara objek dan array pasangan kunci-nilai. Jika to_entries meneruskan objek, maka untuk setiap entri k: v pada input, array output menyertakan {"key": k, "value": v}.

from_entries melakukan konversi sebaliknya, dan with_entries (foo) adalah kependekan dari to_entries | peta (foo) | from_entries, berguna untuk melakukan beberapa operasi ke semua kunci dan nilai suatu objek. from_entries menerima kunci, Kunci, nama, Nama, nilai, dan Nilai sebagai kunci.

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

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

Menggunakan with_entriessteno, ini menjadi:

jq15 < json 'with_entries(select(.value.location=="Stockholm"))'
{
  "FOO": {
    "name": "Donald",
    "location": "Stockholm"
  },
  "BAR": {
    "name": "Walt",
    "location": "Stockholm"
  }
}
spazm
sumber
1
Satu hal yang terus menggigit saya adalah bahwa Anda perlu ingat bahwa ketika menggunakan with_entries(), Anda biasanya ingin juga menggunakan .valuedalam selectklausa. Ini karena to_entriesmakro mengubah entri yang diberikan ke .keydan .valuememasangkan, yang juga terjadi dengan with_entries.
Jaakko