2016-06-30 3 views
11

Ich mag json Dateien filtern jq mit:Wie filtert man Array von Objekten anhand von Elementeigenschaftswerten mit jq?

jq . some.json 

die json Da eine Reihe von Objekten:

{ 
    "theList": [ 
    { 
     "id": 1, 
     "name": "Horst" 
    }, 
    { 
     "id": 2, 
     "name": "Fritz" 
    }, 
    { 
     "id": 3, 
     "name": "Walter" 
    }, 
    { 
     "id": 4, 
     "name": "Gerhart" 
    }, 
    { 
     "id": 5, 
     "name": "Harmut" 
    } 
    ] 
} 

Ich möchte, dass die Liste filtern, um nur die Elemente zu zeigen, mit der ID mit dem Wert 2 und 4, so ist die erwartete Ausgabe:

{ 
    "id": 2, 
    "name": "Fritz" 
}, 
{ 
    "id": 4, 
    "name": "Gerhart" 
} 

Wie filtere ich die Json mit jq? Ich habe mit ausgewählter und Karte rumgespielt, aber nicht irgendwelche von denen an der Arbeit, zum Beispiel:

$ jq '.theList[] | select(.id == 2) or select(.id == 4)' array.json 
true 
+2

** Jeder bitte beachten Sie: ** Die Frage ist über [jq] (http://stedolan.github.io/jq/#), nicht jQuery. –

+0

@ T.J.Crowder YMMD ^^ Und ich klärte in der Frage: D – k0pernikus

Antwort

19

Aus der Dokumentation:

jq '.[] | select(.id == "second")' 

Eingang[{"id": "first", "val": 1}, {"id": "second", "val": 2}]

Ausgabe{"id": "second", "val": 2}

Ich glaube, Sie so etwas tun kann:

jq '.theList[] | select(.id == 2 or .id == 4)' array.json 
+0

'jq '.theList [] | select (.id == 2) oder select (.id == 4) 'array.json' liefert in: 'true' o.O – k0pernikus

+2

Es gibt die Auswertung beider Klauseln zurück, versuchen Sie dies: ' jq' .theList [] | Wählen Sie (.id == 2 oder .id == 4) '' –

+0

' jq' .theList [] | wähle (.id == 2 oder .id == 4) 'array.json' hat den Trick gemacht, du kannst deine Antwort aktualisieren :) – k0pernikus

7

Sie select innerhalb map nutzen könnten.

.theList | map(select(.id == (2, 4))) 

Oder kompakte:

[ .theList[] | select(.id == (2, 4)) ] 

Obwohl auf diese Weise geschrieben ist ein wenig ineffizient, da der Ausdruck für jeden Wert verglichen wird dupliziert. Es wird effizienter sein und möglicherweise besser lesbar geschrieben auf diese Weise:

[ .theList[] | select(any(2, 4; . == .id)) ] 
+0

Kluge Verwendung von [if Verhalten, wenn die Bedingung mehrere Ergebnisse liefert] (https: // github. com/stedolan/jq/blob/master/docs/inhalt/3.manual/manual.yml # L2033-L2035)! – jq170727

0

Hier ist eine Lösung indices mit:

.theList | [ .[map(.id)|indices(2,4)[]] ] 
2

Mit select(.id == (2, 4)) hier ist in der Regel ineffizient (siehe unten).

Wenn Ihr jq IN/1 hat, dann kann es verwendet werden, um eine effizientere Lösung zu erreichen:

.theList[] | select(.id | IN(2,3)) 

Wenn Ihr jq nicht IN/1 hat, dann können Sie es wie folgt definieren:

def IN(s): first(select(s == .)) // false; 

Effizienz

Eine Möglichkeit, die Ineffizienz zu sehen istzu verwenden.Der folgende Ausdruck zum Beispiel führt zu 10 Anrufen debug, während nur 9 prüft auf Gleichheit tatsächlich benötigt: sollte

.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

grundsätzlich mit index/1 effizient sein, aber Zum Zeitpunkt des Schreibens (Oktober 2017) ist seine Implementierung, obwohl sie schnell ist (sie ist in C geschrieben), ineffizient.

Verwandte Themen