Ik filter graag json-bestanden met jq:
jq . some.json
Gezien de json die een reeks objecten bevat:
{
"theList": [
{
"id": 1,
"name": "Horst"
},
{
"id": 2,
"name": "Fritz"
},
{
"id": 3,
"name": "Walter"
},
{
"id": 4,
"name": "Gerhart"
},
{
"id": 5,
"name": "Harmut"
}
]
}
Ik wil die lijst filteren om alleen de elementen weer te geven met id met de waarde 2 en 4, dus de verwachte output is:
{
"id": 2,
"name": "Fritz"
},
{
"id": 4,
"name": "Gerhart"
}
Hoe filter ik de json met jq? Ik heb wat met select en map gespeeld, maar ik heb geen van beide werkend gekregen, bijvoorbeeld:
$ jq '.theList[] | select(.id == 2) or select(.id == 4)' array.json
true
Antwoord 1, autoriteit 100%
Uit de documenten:
jq '.[] | select(.id == "second")'
Invoer
[{"id": "first", "val": 1}, {"id": "second", "val": 2}]
Uitvoer
{"id": "second", "val": 2}
Ik denk dat je zoiets als dit kunt doen:
jq '.theList[] | select(.id == 2 or .id == 4)' array.json
Antwoord 2, autoriteit 18%
Je zou select
kunnen gebruiken binnen map
.
.theList | map(select(.id == (2, 4)))
Of compacter:
[ .theList[] | select(.id == (2, 4)) ]
Hoewel het op die manier is geschreven, is het een beetje inefficiënt omdat de uitdrukking wordt gedupliceerd voor elke waarde die wordt vergeleken. Op deze manier is het efficiënter en mogelijk beter leesbaar:
[ .theList[] | select(any(2, 4; . == .id)) ]
Antwoord 3, autoriteit 6%
Het gebruik van select(.id == (2, 4))
hier is over het algemeen inefficiënt (zie hieronder).
Als uw jq IN/1
heeft, kan deze worden gebruikt om een efficiëntere oplossing te bereiken:
.theList[] | select( .id | IN(2,3))
Als uw jq geen IN/1
heeft, kunt u deze als volgt definiëren:
def IN(s): first(select(s == .)) // false;
Efficiëntie
Een manier om de inefficiëntie te zien, is door debug
te gebruiken. De volgende expressie resulteert bijvoorbeeld in 10 aanroepen voor debug
, terwijl er eigenlijk maar 9 controles op gelijkheid nodig zijn:
.theList[] | select( (.id == (2,3)) | debug )
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",true]
{
"id": 2,
"name": "Fritz"
}
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",true]
{
"id": 3,
"name": "Walter"
}
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",false]
["DEBUG:",false]
index/1
In principe zou het gebruik van index/1
efficiënt moeten zijn, maar op het moment van schrijven (oktober 2017) is de implementatie ervan, hoewel snel (het is geschreven in C), inefficiënt.
Antwoord 4
Hier is een oplossing met behulp van indexen:
.theList | [ .[map(.id)|indices(2,4)[]] ]