Umgang mit JSON-Abfragesprachen, Teil 3 jq zum Filtern von JSON-Ausgaben nutzen

Angesichts der vielen Einsatzbereiche von JSON ist es nützlich, sich mit gängigen Abfrage-Tools für JSON vertraut zu machen. Mit „jq“ widmen wir uns nach JSON Path und JMSPath dem mächtigsten Tool in Trio, bleiben aber aufgrund der Vielzahl an Möglichkeiten vorerst bei den Basics.

Ein paar einfache Filter mit jq.
Ein paar einfache Filter mit jq.
(Bild: Drilling / Red Hat)

JQ (im Folgenden jq) basiert auf dem Konzept von Filtern, die über einen JSON-Stream arbeiten. Jeder Filter nimmt eine Eingabe entgegen und gibt JSON an die Standardausgabe aus. Dabei gibt es zahlreiche vordefinierte Filter, die Sie verwenden können. Darüber hinaus können Sie solche Filter problemlos mit Pipes kombinieren, um schnell komplexe Operationen und Transformationen auf JSON-Daten erstellen und anwenden zu können.

Zuerst muss jq installiert werden. Zwar verfügen die meisten Programmiersprachen über Bibliotheken oder Module, die das Analysieren von JSON-Daten erlauben, leider gilt das gerade nicht für die Bash. Mit jq dagegen können Sie JSON einfach in der Bash-Shell parsen oder sogar XML in JSON konvertieren. Das Installieren von für die gängigen Linux-Distributionen ist simpel, verwenden Sie bei Ubuntu

sudo apt-get install jq

… und bei Red Hat/CentOS …

sudo dnf install jq

Es ist auch möglich, die Binärdatei direkt herunterzuladen oder aus den Quellen zu übersetzen. Zum Überprüfen der Installation rufen Sie jq einfach ohne Parameter auf. Schauen wir uns mit dem Identitätsfilter ‚.‘ zunächst den einfachsten Filter von allen an, der übrigens eine der nützlichsten und am häufigsten verwendeten Funktionen von jq ist:

echo '{"auto":{"name":"audi","farbe":"silber","preis":50000}}' | jq '.'

Der Identitätsfilter gibt die Eingabe unverändert, aber „farbig“ aus.
Der Identitätsfilter gibt die Eingabe unverändert, aber „farbig“ aus.
(Bild: Drilling / Red Hat)

Hier geben Sie einen einfachen JSON-String als Echo zurück und leiten ihn direkt an das jq-Kommando weiter. Dann verwenden Sie den Identitätsfilter ".". Dieser übernimmt die Eingabe übernimmt und gibt sie unverändert als Ausgabe aus, mit der Einschränkung, dass jq die Ausgabe standardmäßig farbig formatiert.

Sie können diesen Filter auch direkt auf eine JSON-Datei anwenden:

jq '.' auto.json

Die aktuelle Position der ISS.
Die aktuelle Position der ISS.
(Bild: Drilling / Red Hat)

Die Möglichkeit, JSON zu verschönern, ist besonders dann nützlich, wenn Sie Daten von einer API abrufen und die Antwort in einem klaren, lesbaren Format anzeigen möchten, wie das z. B. beim Cloud Computing der Fall ist. Es gibt aber auch zahllose öffentlich zugängliche APIs mit denen Sie experimentieren können. So liefert z. B. …

curl http://api.open-notify.org/iss-now.json | jq '.'

… die aktuelle Position der Internationalen Raumstation ISS.

Auflisten aller virtueller Maschinen in Azure.
Auflisten aller virtueller Maschinen in Azure.
(Bild: Drilling / Red Hat)

Rufen Sie doch analog zu unserem Artikel über JMSPath die Lister aller aktuellen virtuellen Maschinen im zuvor authentifizierten Azure-Konto ab:

az vm list | jq

Dabei können Sie auf Eigenschaftswerte zugreifen, indem Sie einen anderen einfachen Filter, den .field-Operator. Verwenden. Um einen Eigenschaftswert zu finden, kombinieren Sie einfach diesen Filter gefolgt vom Eigenschaftsnamen. Testen Sie das anhand unseres einfachen Auto-Datei-Beispiels:

jq ´.auto´ auto.json

Sie können Eigenschaftswerte auch miteinander verketten, womit Sie auf verschachtelte Objekte zugreifen können:

jq '.auto.farbe' auto.json

Wenn Sie mehrere Schlüssel abrufen müssen, können Sie diese durch ein Komma trennen:

jq '.auto.farbe,.auto.preis' auto.json

Enthält eine der Eigenschaften Leerzeichen oder Sonderzeichen, müssen Sie den Eigenschaftsnamen in Anführungszeichen setzen.

Arbeiten mit Arrays

Ein paar einfache Filter mit jq.
Ein paar einfache Filter mit jq.
(Bild: Drilling / Red Hat)

Schauen Sie uns nun an, wie Sie mit Arrays in JSON-Daten arbeiten können. Normalerweise verwenden Sie Arrays, um eine Liste von Elementen darzustellen. Wie bei vielen Programmiersprachen verwendet jq eckige Klammern, um den Anfang und das Ende eines Arrays zu kennzeichnen. Folgendes Beispiel zeigt, wie Sie über ein Array iterieren:

echo '["a","b","c"]' | jq '.[]'

Erstellen Sie nun eine Liste mit Autos als JSON-Dokument:

[
   {
      "name": "audi",
      "farbe": "silber",
      "preis": 50000
   },
   {
      "name": "dacia",
      "farbe": "braun",
      "preis": 10000
   },
   {
      "name": "opel",
      "farbe": "weiss",
      "preis": 20000
   }
]

Hierbei ist jedes Element im Array ein Objekt, das eine Auto darstellt. Nun können Sie z. B. den Namen jedes Autos aus jedem Objekt im Array extrahieren:

jq '.[] | .name' autos.json

Zwei Schreibweisen, die letztendlich das Gleiche tun.
Zwei Schreibweisen, die letztendlich das Gleiche tun.
(Bild: Drilling / Red Hat)

Das Kommando iteriert zuerst mit .[] über das gesamte Array. Danach übergibt es jedes Objekt im Array via Pipe (|) an den nächsten Filter im Befehl. Im letzten Schritt wird mit „.name“ das Namensfeld jedes Objekts ausgegeben: Alternativ können Sie mit …

jq '.[].name' autos.json

… auch direkt auf die Eigenschaft für jedes Objekt im Array zugreifen. Und wie bei allen Arrays können Sie auch direkt auf eines der Elemente im Array zugreifen, indem Sie den jeweiligen Index übergeben:

jq '.[2].preis' autos.json

Funktionen nutzen

Eigentlich ist jq viel mehr als ein Filter und verfügt über viele leistungsstarke integrierte Funktionen, mit denen Sie eine Vielzahl nützlicher Operationen ausführen können. Eine dieser praktischen Funktionen für Arrays und Objekte ist die Längenfunktion. Diese können Sie nutzen, um die Länge des Arrays oder die Anzahl der Eigenschaften eines Objekts zurückzugeben:

Jetzt Newsletter abonnieren

Täglich die wichtigsten Infos zu Softwareentwicklung und DevOps

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung.

Aufklappen für Details zu Ihrer Einwilligung
jq '.autos | length' autos.json

Mit den Funktionen „min“ und „max“ hingegen finden Sie schnell das minimale oder maximale Element eines Eingabe-Arrays. Mit der Funktion „test“ können Sie dagegen prüfen, ob eine Eingabe mit einem bestimmten regulären Ausdruck übereinstimmt: Folgendes Beispiel gibt den Preis sämtlicher Autos aus, deren Name mit dem Buchstaben „a“ beginnt.

Jq bringt sogar viele leistungsfähige eingebaute Funktionen mit.
Jq bringt sogar viele leistungsfähige eingebaute Funktionen mit.
(Bild: Drilling / Red Hat)

Ein weiterer häufiger Anwendungsfall besteht darin, eindeutige Vorkommen eines bestimmten Werts in einem Array zu ermitteln oder Duplikate zu entfernen. Das vorangestellte Beispiel prüft, wie viele einzigartige Farben das autos-Dokument enthält.

Schließlich unterstützt jq auch das Slicing von Arrays. Dies ist besonders nützlich, wenn Sie ein Sub-Array eines Arrays zurückgeben müssen.

echo '[1,2,3,4,5,6,7,8,9,10]' | jq '.[6:9]'

Wie viele moderne Programmiersprachen beherrscht jq sogar Slicing.
Wie viele moderne Programmiersprachen beherrscht jq sogar Slicing.
(Bild: Drilling / Red Hat)

In diesem Beispiel ist das Ergebnis ein neues Array mit einer Länge von 3, das die Elemente von Index 5 (einschließlich) bis Index 8 (exklusiv) enthält. Es ist ebenfalls möglich, einen der Indizes wegzulassen:

echo '[1,2,3,4,5,6,7,8,9,10]' | jq '.[:5]' | jq '.[-2:]'

(ID:47489255)