jq — JSON-Abfrage und -Transformation
Selektive Lese-Regel
Beginnen Sie mit:
references/senior-master-standard.mdreferences/usage-routing.mdreferences/quality-checklist.md
Laden Sie dann nur die vererbten Dokumente, Skripte, Assets oder Beispiele, die zur tatsächlichen Aufgabe des Benutzers passen.
Übersicht
jq ist das standardmäßige CLI-Tool zum Abfragen und Umformen von JSON. Dieser Skill behandelt praktische, expertenhafte Nutzung: Filtern tief verschachtelter Daten, Transformieren von Strukturen, Aggregieren von Werten und Einbinden von jq in Shell-Pipelines. Jedes Beispiel ist kopierfertig für echte Arbeitsabläufe.
Wann dieser Skill zu verwenden ist
- Verwenden Sie ihn beim Parsen von JSON-Ausgaben von APIs, CLI-Tools (AWS, GitHub, kubectl, docker) oder Logdateien
- Verwenden Sie ihn beim Transformieren von JSON-Strukturen (Schlüssel umbenennen, Arrays glätten, Datensätze gruppieren)
- Verwenden Sie ihn, wenn der Benutzer
jqin einem Bash-Skript oder einem Einzeiler benötigt - Verwenden Sie ihn beim Erklären, was ein komplexer
jq-Ausdruck tut
Funktionsweise
jq nimmt einen Filterausdruck und wendet ihn auf die JSON-Eingabe an. Filter verketten sich mit Pipes (|), und jq behandelt Arrays, Objekte, Strings, Zahlen, Booleans und null nativ.
Grundlegende Selektion
# Ein Feld extrahieren
echo '{"name":"alice","age":30}' | jq '.name'
# "alice"
# Verschachtelter Zugriff
echo '{"user":{"email":"[email protected]"}}' | jq '.user.email'
# Array-Index
echo '[10, 20, 30]' | jq '.[1]'
# 20
# Array-Slice
echo '[1,2,3,4,5]' | jq '.[2:4]'
# [3, 4]
# Alle Array-Elemente
echo '[{"id":1},{"id":2}]' | jq '.[]'
Filtern mit select
# Nur übereinstimmende Elemente behalten
echo '[{"role":"admin"},{"role":"user"},{"role":"admin"}]' \
| jq '[.[] | select(.role == "admin")]'
# Numerischer Vergleich
curl -s https://api.github.com/repos/owner/repo/issues \
| jq '[.[] | select(.comments > 5)]'
# Prüfen, ob ein Feld existiert und nicht null ist
jq '[.[] | select(.email != null)]'
# Bedingungen kombinieren
jq '[.[] | select(.active == true and .score >= 80)]'
Mapping und Transformation
# Ein Feld aus jedem Array-Element extrahieren
echo '[{"name":"alice","age":30},{"name":"bob","age":25}]' \
| jq '[.[] | .name]'
# ["alice", "bob"]
# Kurzform: map()
jq 'map(.name)'
# Ein neues Objekt pro Element erstellen
jq '[.[] | {user: .name, years: .age}]'
# Ein berechnetes Feld hinzufügen
jq '[.[] | . + {senior: (.age > 28)}]'
# Schlüssel umbenennen
jq '[.[] | {username: .name, email_address: .email}]'
Aggregation und Reduce
# Alle Werte summieren
echo '[1, 2, 3, 4, 5]' | jq 'add'
# 15
# Ein Feld über Objekte hinweg summieren
jq '[.[].price] | add'
# Elemente zählen
jq 'length'
# Max / Min
jq 'max_by(.score)'
jq 'min_by(.created_at)'
# reduce: benutzerdefinierter Akkumulator
echo '[1,2,3,4,5]' | jq 'reduce .[] as $x (0; . + $x)'
# 15
# Nach Feld gruppieren
jq 'group_by(.department)'
# Anzahl pro Gruppe
jq 'group_by(.status) | map({status: .[0].status, count: length})'
String-Interpolation und Formatierung
# String-Interpolation
jq -r '.[] | "\(.name) ist \(.age) Jahre alt"'
# Als CSV formatieren (ohne Kopfzeile)
jq -r '.[] | [.name, .age, .email] | @csv'
# Als TSV formatieren
jq -r '.[] | [.name, .score] | @tsv'
# URL-codieren eines Wertes
jq -r '.query | @uri'
# Base64-codieren
jq -r '.data | @base64'
Arbeiten mit Schlüsseln und Pfaden
# Alle Schlüssel der obersten Ebene auflisten
jq 'keys'
# Prüfen, ob ein Schlüssel existiert
jq 'has("email")'
# Einen Schlüssel löschen
jq 'del(.password)'
# Verschachtelte Schlüssel aus jedem Element löschen
jq '[.[] | del(.internal_id, .raw_payload)]'
# Rekursive Abwärtssuche: alle Werte für einen Schlüssel im gesamten Baum finden
jq '.. | .id? // empty'
# Alle Blattpfade ermitteln
jq '[paths(scalars)]'
Bedingungen und Fehlerbehandlung
# if-then-else
jq 'if .score >= 90 then "A" elif .score >= 80 then "B" else "C" end'
# Alternativoperator: Fallback verwenden, wenn null oder false
jq '.nickname // .name'
# try-catch: Fehler überspringen statt anzuhalten
jq '[.[] | try .nested.value catch null]'
# null-Ausgabe mit // empty unterdrücken
jq '.[] | .optional_field // empty'
Praktische Shell-Integration
# Aus Datei lesen
jq '.users' data.json
# Kompakte Ausgabe (keine Leerzeichen) für weitere Pipes
jq -c '.[]' records.json | while IFS= read -r record; do
echo "Verarbeite: $record"
done
# Shell-Variable in jq übergeben
STATUS="active"
jq --arg s "$STATUS" '[.[] | select(.status == $s)]'
# Eine Zahl übergeben
jq --argjson threshold 42 '[.[] | select(.value > $threshold)]'
# Mehrere JSON-Zeilen in ein Array einlesen
jq -s '.' records.ndjson
# Mehrere Dateien: alle in ein Array einlesen
jq -s 'add' file1.json file2.json
# Null-sichere Pipeline aus einem Befehl
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, status: .status.phase}'
# GitHub CLI: PR-Nummern extrahieren
gh pr list --json number,title | jq -r '.[] | "\(.number)\t\(.title)"'
# AWS CLI: laufende Instance-IDs auflisten
aws ec2 describe-instances \
| jq -r '.Reservations[].Instances[] | select(.State.Name=="running") | .InstanceId'
# Docker: Containernamen und Images anzeigen
docker inspect $(docker ps -q) | jq -r '.[] | "\(.Name)\t\(.Config.Image)"'
Fortgeschrittene Muster
# Ein Objekt aus Arrays in ein Array aus Objekten transponieren
# Eingabe: {"names":["a","b"],"scores":[10,20]}
jq '[.names, .scores] | transpose | map({name: .[0], score: .[1]})'
# Eine Ebene glätten
jq 'flatten(1)'
# Nach Feld eindeutig machen
jq 'unique_by(.email)'
# Sortieren, deduplizieren und neu indizieren
jq '[.[] | .name] | unique | sort'
# walk: Transformation auf jeden Knoten rekursiv anwenden
jq 'walk(if type == "string" then ascii_downcase else . end)'
# env: Umgebungsvariablen innerhalb von jq lesen
export API_KEY=secret
jq -n 'env.API_KEY'
Best Practices
- Verwenden Sie immer
-r(Rohausgabe), wenn Siejq-Ergebnisse an Shell-Variablen oder andere Befehle übergeben, um JSON-String-Anführungszeichen zu entfernen - Verwenden Sie
--arg/--argjson, um Shell-Variablen sicher zu injizieren — interpolieren Sie Shell-Variablen niemals direkt in Filterstrings - Bevorzugen Sie
map(f)gegenüber[.[] | f]für bessere Lesbarkeit - Verwenden Sie
-c(kompakt) für zeilenweise getrennte JSON-Pipelines; lassen Sie es für menschenlesbares Debugging weg - Testen Sie Filter interaktiv mit
jq -nund wörtlicher Eingabe, bevor Sie sie in Skripte einbetten - Verwenden Sie
empty, um unerwünschte Elemente zu entfernen, anstatt sie aufnullzu filtern
Sicherheitshinweise
jqist von Haus aus schreibgeschützt — es kann keine Dateien schreiben oder Befehle ausführen- Vermeiden Sie es, unvertraute JSON-Feldwerte direkt in Shell-Befehle einzubetten; zitieren Sie immer oder verwenden Sie
--arg
Häufige Fallstricke
-
Problem:
jqgibtnullstatt des erwarteten Wertes aus Lösung: Prüfen Sie auf Tippfehler in Schlüsselnamen; verwenden Siekeys, um die tatsächlichen Feldnamen zu überprüfen. Denken Sie daran, dass JSON case-sensitiv ist. -
Problem: Zahlen werden im Ergebnis als Strings in Anführungszeichen ausgegeben Lösung: Verwenden Sie
--argjsonanstelle von--arg, wenn Sie numerische Werte injizieren. -
Problem: Der Filter funktioniert im Terminal, schlägt aber in einem Skript fehl Lösung: Stellen Sie sicher, dass der Filterstring im Shell-Kontext einfache Anführungszeichen verwendet, um Variablenexpansion zu verhindern. Beispiel:
jq '.field'nichtjq ".field". -
Problem:
addgibtnullfür ein leeres Array zurück Lösung: Verwenden Sieadd // 0oderadd // "", um einen Fallback-Standardwert bereitzustellen. -
Problem: Streaming großer Dateien ist langsam Lösung: Verwenden Sie
jq --streamoder wechseln Sie für sehr große Dateien zujstream/gron.
Verwandte Skills
@bash-pro— jq-Aufrufe in robuste Shell-Skripte einbetten@bash-linux— Allgemeine Shell-Pipeline-Muster@github-automation— jq mit GitHub CLI JSON-Ausgabe verwenden
Einschränkungen
- Verwenden Sie diesen Skill nur, wenn die Aufgabe eindeutig mit dem oben beschriebenen Umfang übereinstimmt.
- Betrachten Sie die Ausgabe nicht als Ersatz für umgebungsspezifische Validierung, Tests oder Expertenüberprüfung.
- Halten Sie an und fragen Sie nach Klärung, wenn erforderliche Eingaben, Berechtigungen, Sicherheitsgrenzen oder Erfolgskriterien fehlen.