jq - JSON Processor
Tool-Lektion | 30 Minuten
JSON ist überall (APIs, Configs, Logs), aber:
Lernziele
- Verstehen warum dieses Tool wichtig ist
- Die wichtigsten Einsatzgebiete kennen
- Installation und grundlegende Nutzung beherrschen
- Production-ready Patterns anwenden
- Real-World Use Cases umsetzen
jq - JSON Processor
🚀 Claude Code Relevanz: jq ist unverzichtbar in Claude Code Workflows, weil du damit API-Responses filtern, package.json analysieren und JSON-Logs parsen kannst - alles direkt im Terminal ohne externe Tools.
Berechtigung - Warum jq?
Das Problem mit JSON im Terminal
JSON ist überall (APIs, Configs, Logs), aber:
- ❌ Unleserlich (ein langer String)
- ❌ Schwer zu filtern
- ❌ Keine Extraktion von Fields
- ❌ Keine Transformationen
- ❌ Schwer zu debuggen
Beispiel: API-Response ohne jq:
curl api.example.com/users
# {"users":[{"id":1,"name":"Alice","email":"alice@example.com"},{"id":2,"name":"Bob","email":"bob@example.com"}]}
→ Unleserliche Wall of Text
Die Lösung: jq
jq ist ein Command-Line JSON Processor:
- ✅ Pretty-Print (Formatting + Colors)
- ✅ Filtern (nur bestimmte Fields)
- ✅ Transformieren (Shape von JSON ändern)
- ✅ Suchen (find specific values)
- ✅ Aggregieren (Sum, Count, Group)
- ✅ Scripting (komplexe JSON-Logik)
Gleicher Response mit jq:
curl api.example.com/users | jq '.users[] | {name, email}'
# {
# "name": "Alice",
# "email": "alice@example.com"
# }
# {
# "name": "Bob",
# "email": "bob@example.com"
# }
→ Lesbar, gefiltert, perfekt!
Ergebnis: JSON-Processing ist jetzt trivial, nicht frustrierend.
Zwecke - Wofür du jq einsetzt
. **Pretty-Print JSON**
API-Responses und JSON-Dateien sind oft als ein einziger langer String formatiert, der fuer Menschen praktisch unleserlich ist. jq's einfachster Befehl . (Identity-Operator) nimmt das komprimierte JSON entgegen und gibt es mit korrekter Einrueckung, Zeilenumbruechen und Farbhervorhebung zurueck. Stell dir vor, du bekommst eine API-Response mit verschachtelten Objekten in einer einzigen Zeile - jq '.' macht daraus einen sauber formatierten, mehrzeiligen Output in dem du die Struktur sofort erkennst. Das ist der am haeufigsten genutzte jq-Befehl und sollte in jedem Entwickler-Toolkit vorhanden sein. Kombiniere ihn mit cat oder pipe ihn direkt an einen curl-Output.
cat config.json | jq '.'
. **Extract Fields**
In den meisten Faellen brauchst du nicht das gesamte JSON-Objekt, sondern nur bestimmte Felder daraus. Mit der Punkt-Notation (.key) extrahierst du einzelne Werte aus einem JSON-Objekt, und mit verschachtelter Notation (.key.subkey) greifst du auf tiefer liegende Werte zu. Stell dir vor, eine API gibt dir ein komplettes User-Objekt mit 30 Feldern zurueck, aber du brauchst nur den Namen - .name gibt dir genau diesen einen Wert. Das ist unschlagbar schnell im Vergleich zum manuellen Durchsuchen des gesamten JSON-Outputs. Besonders in Kombination mit Pipes ist das extrem nuetzlich fuer Shell-Skripte.
curl api.example.com/user | jq '.name'
. **Filter Arrays**
JSON-Arrays enthalten oft hunderte Eintraege, von denen du nur bestimmte brauchst. Mit select() filterst du Array-Elemente anhand von Bedingungen - zum Beispiel nur aktive User oder nur Bestellungen ueber einem bestimmten Betrag. Der [] Operator iteriert ueber alle Array-Elemente, und select() laesst nur die durch, die die Bedingung erfuellen. Stell dir vor, du hast eine users.json mit 500 Eintraegen und willst nur die aktiven User sehen - select(.active == true) filtert die Liste sofort herunter. Das ist deutlich schneller und praeziser als manuelles Durchsuchen.
jq '.users[] | select(.active == true)' users.json
. **Transform JSON**
Wenn du Daten von einer API bekommst und sie in einem anderen Format an eine andere API senden musst, ist jq's Transformations-Faehigkeit unverzichtbar. Du kannst Felder umbenennen, zusammenfuegen, hinzufuegen oder entfernen - alles in einem einzigen Befehl. Stell dir vor, API A gibt dir {userId, firstName, lastName} und API B erwartet {id, fullName} - mit jq transformierst du das Format in Sekunden statt ein Python-Skript dafuer zu schreiben. Das ist besonders wertvoll in Daten-Pipelines und bei der Integration verschiedener Services. Das Ergebnis ist ein neues JSON-Objekt im gewuenschten Format.
jq '{id: .userId, fullName: (.firstName + " " + .lastName)}' user.json
. **Aggregate Data**
jq kann nicht nur filtern und transformieren, sondern auch Daten aggregieren - summieren, zaehlen, gruppieren und Durchschnitte berechnen. Das macht jq zu einem maechtigen Werkzeug fuer schnelle Datenanalysen direkt im Terminal. Stell dir vor, du hast eine orders.json mit hunderten Bestellungen und willst den Gesamtumsatz wissen - ein einziger jq-Befehl berechnet die Summe aller Preise. Das ist deutlich schneller als die Daten in Excel zu importieren oder ein Python-Skript zu schreiben. Besonders fuer schnelle Ad-hoc-Analysen ist jq unschlagbar effizient.
jq '[.items[].price] | add' orders.json
Verwendung - Wie du jq einsetzt
Installation
macOS (Homebrew):
Auf macOS installierst du jq am schnellsten ueber Homebrew. Das Paket hat keine zusaetzlichen Abhaengigkeiten und ist sofort nach der Installation einsatzbereit. Pruefe mit echo '{"test":1}' | jq '.' ob die Installation funktioniert hat. jq ist eines der am haeufigsten genutzten CLI-Tools und wird in fast jedem Terminal-Workflow benoetigt. Die Installation dauert nur wenige Sekunden.
brew install jq
Ubuntu/Debian:
Auf Debian-basierten Systemen ist jq als Standardpaket in den Repositories verfuegbar. Die Installation ist unkompliziert und jq ist sofort nach der Installation nutzbar. Die apt-Version ist in der Regel aktuell genug fuer alle gaengigen Anwendungsfaelle. jq hat minimale Abhaengigkeiten und benoetigt kaum Speicherplatz. Teste mit jq --version ob die Installation erfolgreich war.
sudo apt install jq
Arch Linux:
Arch Linux bietet jq ueber das Extra-Repository an. Wie bei allen Arch-Paketen bekommst du immer die aktuellste Version. jq ist ein essenzielles Tool das in keiner Linux-Installation fehlen sollte. Die Installation ist schnell und unkompliziert. Danach steht jq sofort im Terminal zur Verfuegung.
sudo pacman -S jq
Windows (Chocolatey):
Auf Windows installierst du jq am besten ueber Chocolatey oder Scoop. Nach der Installation funktioniert jq in PowerShell und im Windows Terminal. Alternativ kannst du das Binary auch manuell von der offiziellen Website herunterladen und in deinen PATH legen. jq funktioniert auf Windows genauso wie auf Linux und macOS. Teste mit echo '{"test":1}' | jq '.' ob alles funktioniert.
choco install jq
Quick Start (30 Sekunden)
Basis-Usage:
Diese Grundbefehle zeigen dir die wichtigsten jq-Operationen: Pretty-Print, Feld-Extraktion, verschachtelte Zugriffe und Array-Zugriffe. jq arbeitet immer als Filter - es nimmt JSON als Input entgegen und gibt transformiertes JSON als Output zurueck. Der einfachste Filter ist . (Identity), der das JSON nur formatiert. Mit .key extrahierst du einen einzelnen Wert, mit .key.sub greifst du auf verschachtelte Werte zu, und mit .[0] auf ein bestimmtes Array-Element. Stell dir vor, du bekommst eine komplexe API-Response und willst nur den Namen des ersten Users - jq '.users[0].name' gibt dir genau das. Beachte, dass jq standardmaessig Strings mit Anfuehrungszeichen ausgibt - nutze -r fuer Raw-Output ohne Quotes.
# Pretty-Print
echo '{"name":"Alice","age":30}' | jq '.'
# Extract Field
echo '{"name":"Alice","age":30}' | jq '.name'
# Extract Nested
echo '{"user":{"name":"Alice"}}' | jq '.user.name'
# Array Access
echo '{"users":["Alice","Bob"]}' | jq '.users[0]'
Wichtigste Operatoren:
Diese Operatoren bilden die Grundlage jeder jq-Query. Der Punkt . ist der Identity-Operator, .key greift auf ein Objekt-Feld zu, [] iteriert ueber ein Array, und | (Pipe) verkettet Operationen aehnlich wie in der Shell. Der select()-Operator filtert Elemente basierend auf einer Bedingung, und map() wendet eine Transformation auf jedes Array-Element an. Stell dir vor, du willst aus einem Array von Usern die E-Mail-Adressen aller aktiven User extrahieren - du kombinierst [] | select(.active) | .email. Lerne diese Operatoren und du deckst 90% aller jq-Anwendungsfaelle ab.
# . Identity (pass-through, pretty-print)
# .key Access key
# .key.sub Nested access
# .[0] Array index
# .[] Array iteration
# | Pipe (wie Shell)
# select() Filter
# map() Transform array
Advanced Usage
1. Array Operations:
jq bietet umfangreiche Array-Operationen fuer die Arbeit mit Listen von Daten. Mit .[] iterierst du ueber alle Elemente, mit .[index] greifst du auf ein bestimmtes Element zu, und mit .[start:end] schneidest du einen Bereich aus. Die Funktionen first, last und length geben dir schnellen Zugriff auf das erste Element, das letzte Element und die Gesamtanzahl. Stell dir vor, du hast ein Array mit 100 Eintraegen und willst nur die ersten 5 sehen - .[0:5] gibt dir genau das. Diese Operationen lassen sich mit Pipes kombinieren fuer komplexere Abfragen.
# Alle Array-Items
echo '[1,2,3]' | jq '.[]'
# Mit Index
echo '["a","b","c"]' | jq '.[1]'
# Slice
echo '[1,2,3,4,5]' | jq '.[1:3]'
# First/Last
echo '[1,2,3]' | jq 'first'
echo '[1,2,3]' | jq 'last'
# Length
echo '[1,2,3]' | jq 'length'
2. Object Construction:
Mit jq kannst du neue JSON-Objekte konstruieren, Felder hinzufuegen, entfernen oder umbenennen. Die geschweiften Klammern {} erstellen ein neues Objekt, + fuegt Felder hinzu, del() entfernt Felder und * merged zwei Objekte. Stell dir vor, du bekommst User-Daten von einer API und musst sie fuer eine andere API umstrukturieren - mit Object Construction formst du das JSON in einem Befehl um. Das ist besonders nuetzlich fuer Daten-Migrationen und API-Integrationen. Die Syntax ist intuitiv und laesst sich gut mit Pipes verketten.
# New Object
jq '{name: .username, email: .emailAddress}' user.json
# Add Field
jq '. + {timestamp: now}' data.json
# Remove Field
jq 'del(.password)' user.json
# Merge Objects
jq '. * {active: true}' user.json
3. Filtering:
Filtering ist eine der maechtigsten Funktionen von jq. Mit select() filterst du Array-Elemente basierend auf Bedingungen wie Vergleichsoperatoren, regulaeren Ausdruecken oder der Existenz bestimmter Keys. Du kannst mehrere Bedingungen mit and und or kombinieren. Stell dir vor, du hast eine Liste von 10.000 Log-Eintraegen und willst nur die Errors der letzten Stunde finden - select(.level == "error" and .timestamp > "2026-02-12T15:00") filtert die Liste praezise. Der test()-Operator ermoeglicht Regex-Matching, und has() prueft ob ein Key existiert.
# Select
jq '.users[] | select(.age > 30)' users.json
# Multiple Conditions
jq '.users[] | select(.age > 30 and .active == true)' users.json
# Regex
jq '.emails[] | select(test("@gmail.com$"))' data.json
# Has Key
jq '.users[] | select(has("email"))' users.json
4. Transformation:
Mit map() wendest du eine Transformation auf jedes Element eines Arrays an, und select() innerhalb von map() filtert gleichzeitig. group_by() gruppiert Array-Elemente nach einem gemeinsamen Feld, und sort_by() sortiert sie nach einem beliebigen Kriterium. Stell dir vor, du hast eine Liste von Produkten und willst sie nach Kategorie gruppieren und innerhalb jeder Gruppe nach Preis sortieren - mit jq erledigst du das in einer Zeile. reverse dreht die Sortierreihenfolge um, was nuetzlich ist wenn du die teuersten oder neuesten Eintraege zuerst sehen willst.
# Map
jq '.users | map({name, email})' data.json
# Map + Select
jq '.users | map(select(.age > 30))' data.json
# Group By
jq 'group_by(.category)' items.json
# Sort
jq 'sort_by(.age)' users.json
# Reverse
jq 'sort_by(.age) | reverse' users.json
5. Aggregation:
jq bietet eingebaute Aggregationsfunktionen fuer schnelle Datenanalysen. length zaehlt Elemente, add summiert Werte, add / length berechnet den Durchschnitt, und min/max finden Extremwerte. unique entfernt Duplikate aus einem Array. Stell dir vor, du hast eine orders.json und willst den Durchschnittlichen Bestellwert berechnen - [.orders[].amount] | add / length gibt dir die Antwort in Millisekunden. Diese Funktionen machen jq zu einem leichtgewichtigen Datenanalyse-Tool, das kein Python oder Excel erfordert.
# Count
jq '.users | length' data.json
# Sum
jq '[.items[].price] | add' orders.json
# Average
jq '[.items[].price] | add / length' orders.json
# Min/Max
jq '[.items[].price] | min' orders.json
jq '[.items[].price] | max' orders.json
# Unique
jq '.tags | unique' data.json
6. Conditionals:
jq unterstuetzt If-Then-Else-Ausdruecke fuer bedingte Logik innerhalb von Transformationen. Du kannst einzelne Werte basierend auf Bedingungen unterschiedlich verarbeiten, Kategorien zuweisen oder Default-Werte setzen. Das if-Statement in jq endet immer mit end, und elif ermoeglicht mehrere Bedingungen. Stell dir vor, du willst User nach Alter in Kategorien einteilen - mit if-elif-else weist du jedem User die richtige Kategorie zu. Beachte, dass jq-Conditionals Ausdruecke sind die einen Wert zurueckgeben, nicht wie in Programmiersprachen.
# If-Then-Else
jq 'if .age > 18 then "adult" else "minor" end' user.json
# Ternary (alternative)
jq '.age > 18 | if . then "adult" else "minor" end' user.json
# Multiple Conditions
jq 'if .age < 13 then "child"
elif .age < 18 then "teenager"
else "adult"
end' user.json
7. String Operations:
jq bietet verschiedene String-Operationen fuer Textmanipulation innerhalb von JSON. Du kannst Strings verketten (+), aufteilen (split()), ersetzen (gsub()) und die Gross-/Kleinschreibung aendern (ascii_downcase/ascii_upcase). Stell dir vor, du hast User-Daten mit separaten Vor- und Nachname-Feldern und brauchst den vollen Namen als einen String - mit + verkettst du die Felder. Der split()-Operator ist nuetzlich um E-Mail-Adressen in Benutzername und Domain aufzuteilen. Diese Operationen lassen sich nahtlos mit den anderen jq-Funktionen kombinieren.
# Concat
jq '.firstName + " " + .lastName' user.json
# Split
jq '.email | split("@")' user.json
# Replace
jq '.text | gsub("old"; "new")' data.json
# Lowercase/Uppercase
jq '.name | ascii_downcase' user.json
jq '.name | ascii_upcase' user.json
Best Practices
. **Aliases fuer haeufige Use-Cases**
Die am haeufigsten genutzten jq-Operationen verdienen eigene Aliases, damit du sie nicht jedes Mal ausschreiben musst. Pretty-Print mit jqp, Keys anzeigen mit jqk, Laenge zaehlen mit jql und sortierte Keys mit jqs decken die Mehrheit der alltaeglichen Anwendungsfaelle ab. Stell dir vor, du bekommst eine grosse JSON-Datei und willst schnell die Top-Level-Keys sehen - jqk data.json ist schneller als jq 'keys' data.json. Fuege diese Aliases in deine .bashrc oder .zshrc ein, damit sie bei jedem Terminal-Start verfuegbar sind.
# In ~/.bashrc oder ~/.zshrc
alias jqp='jq "."' # Pretty-Print
alias jqk='jq "keys"' # Show Keys
alias jql='jq "length"' # Count Items
alias jqs='jq -S "."' # Sort Keys
. **Combine mit httpie/curl**
Die Kombination von httpie (oder curl) mit jq ist der Standard-Workflow fuer API-Arbeit im Terminal. httpie holt die Daten von der API und jq filtert, transformiert oder analysiert sie. Die Pipe (|) verbindet beide Tools nahtlos. Stell dir vor, du willst die Namen und E-Mail-Adressen aller GitHub-User eines Repos extrahieren - ein einziger Befehl mit curl und jq genuegt. Diese Kombination ersetzt in vielen Faellen grafische API-Clients wie Postman. Nutze -s (silent) bei curl um Fortschrittsbalken zu unterdruecken.
# API-Daten direkt filtern
http GET api.example.com/users | jq '.[] | {name, email}'
# curl + jq
curl -s api.github.com/users/octocat | jq '{login, name, public_repos}'
. **Pipe in Files**
Gefilterte oder transformierte JSON-Daten willst du oft in eine neue Datei speichern, um sie weiterzuverarbeiten oder zu archivieren. Mit der Shell-Umleitung > speicherst du den jq-Output direkt in eine Datei. Das ist nuetzlich fuer die Erstellung von Test-Fixtures, Daten-Backups oder die Vorbereitung von Daten fuer andere Tools. Stell dir vor, du hast eine grosse users.json und willst nur die aktiven User in einer separaten Datei speichern - jq filtert und die Shell speichert. Beachte, dass > die Zieldatei ueberschreibt - nutze >> fuer Append.
# Filter + Save
jq '.users[] | select(.active == true)' users.json > active-users.json
# Transform + Save
jq 'map({id, name})' data.json > simplified.json
. **Raw Output (fuer Scripts)**
Standardmaessig gibt jq Strings mit Anfuehrungszeichen aus - das ist korrekt fuer JSON, aber stoerend wenn du die Werte in Shell-Variablen oder Loops verwenden willst. Mit dem -r Flag (raw output) entfernt jq die Anfuehrungszeichen, sodass du die Werte direkt in Shell-Skripten verwenden kannst. Stell dir vor, du willst alle E-Mail-Adressen aus einer JSON-Datei extrahieren und in einer for-Schleife verarbeiten - ohne -r haetten die Werte Anfuehrungszeichen und wuerden dein Skript brechen. Der -r Flag ist einer der am haeufigsten genutzten jq-Optionen fuer Scripting.
# Mit Quotes (default)
jq '.name' user.json
# "Alice"
# Ohne Quotes (raw)
jq -r '.name' user.json
# Alice
# Perfect für Loops
for email in $(jq -r '.users[].email' users.json); do
echo "Sending to $email"
done
. **Null-Handling**
JSON-Daten enthalten oft fehlende Felder oder null-Werte, die deine jq-Queries zum Absturz bringen koennen. Der // Operator (Alternative Operator) definiert einen Fallback-Wert fuer den Fall dass ein Feld null oder nicht vorhanden ist. Mit dem ?-Operator (try-Operator) unterdrueckst du Fehler bei nicht existierenden Pfaden. Stell dir vor, du verarbeitest User-Daten und manche User haben kein E-Mail-Feld gesetzt - ohne Null-Handling bricht dein Skript ab. Mit .email // "N/A" bekommst du stattdessen einen sinnvollen Default-Wert. Robustes Null-Handling ist besonders wichtig bei der Verarbeitung von API-Daten, wo die Datenqualitaet variieren kann.
# Crash bei null
jq '.user.email' data.json # Error wenn .user null
# Safe (optional chaining)
jq '.user?.email // "N/A"' data.json
# Alternative Operator
jq '.email // .fallbackEmail // "unknown"' user.json
. **Multi-File Processing**
jq kann mehrere JSON-Dateien gleichzeitig verarbeiten, was nuetzlich ist wenn du Daten aus verschiedenen Quellen zusammenfuehren oder vergleichen willst. Mit dem -s Flag (slurp) liest jq alle Dateien ein und kombiniert sie in ein einziges Array. Ohne -s verarbeitet jq jede Datei einzeln und gibt separate Outputs aus. Stell dir vor, du hast Daten in drei separaten JSON-Dateien und willst sie zu einer einzigen zusammenfuegen - jq -s '.' kombiniert sie in einem Array. Das ist auch nuetzlich fuer Batch-Verarbeitung von JSON-Logs oder Export-Dateien.
# Combine Multiple JSON-Files
jq -s '.' file1.json file2.json file3.json
# Process Multiple Files
jq '.name' *.json
. **Claude Code Workflows**
In Claude Code Sessions ist jq ein unverzichtbarer Begleiter fuer die Analyse von API-Responses, Config-Dateien und JSON-Logs. Du nutzt jq um die Abhaengigkeiten in package.json zu inspizieren, API-Responses zu filtern oder JSON-Logs nach Fehlern zu durchsuchen. Stell dir vor, Claude Code hat eine neue API-Route implementiert und du willst die Response analysieren - mit jq extrahierst du genau die Felder die relevant sind. jq kann auch Test-Daten generieren, die du fuer Unit-Tests oder manuelle Tests brauchst. Die Kombination mit httpie ergibt einen vollstaendigen API-Test-Workflow im Terminal.
# API-Response analysieren
http GET localhost:3000/api/users | jq '.[] | {id, name}'
# Config-Files filtern
jq '.dependencies | keys' package.json
# Logs parsen (JSON-Logs)
cat logs.json | jq 'select(.level == "error") | {timestamp, message}'
# Test-Data generieren
jq -n '{name: "Test", email: "test@example.com", age: 25}' > test-user.json
Beispiele - Real-World Use-Cases
Beispiel 1: API-Response Pretty-Print
Szenario: API gibt unleserliches JSON zurück.
# Ohne jq (schlecht)
curl api.github.com/users/octocat
# {"login":"octocat","id":583231,"node_id":"MDQ6VXNlcjU4MzIzMQ==","avatar_url":"https://avatars.githubusercontent.com/u/583231?v=4",...}
# Mit jq (gut)
curl -s api.github.com/users/octocat | jq '.'
# {
# "login": "octocat",
# "id": 583231,
# "name": "The Octocat",
# "public_repos": 8,
# "followers": 12345
# }
# Nur relevante Fields
curl -s api.github.com/users/octocat | jq '{login, name, public_repos, followers}'
Zeit gespart: 1 Minute vs. manuelles Kopieren in JSON-Formatter
Beispiel 2: Package.json Dependencies extrahieren
Szenario: Welche Dependencies hat das Projekt?
# Alle Dependencies
jq '.dependencies | keys' package.json
# Output:
# [
# "express",
# "react",
# "typescript"
# ]
# Mit Versionen
jq '.dependencies' package.json
# Count
jq '.dependencies | length' package.json
# 42
# Find specific Package
jq '.dependencies | has("react")' package.json
# true
Produktivität: Instant Overview
Beispiel 3: Filter Large JSON (Logs)
Szenario: 10k Log-Entries, nur Errors relevant.
# Logs-File:
# [
# {"timestamp": "2026-02-12", "level": "info", "message": "..."},
# {"timestamp": "2026-02-12", "level": "error", "message": "Failed to connect"},
# ...
# ]
# Nur Errors
jq '.[] | select(.level == "error")' logs.json
# Errors heute
jq '.[] | select(.level == "error" and .timestamp | startswith("2026-02-12"))' logs.json
# Count Errors
jq '[.[] | select(.level == "error")] | length' logs.json
# Error-Messages only
jq '.[] | select(.level == "error") | .message' logs.json
Resultat: 10k Zeilen → 20 relevante Errors in Sekunden
Beispiel 4: Transform für andere API
Szenario: API A gibt Data, du brauchst Format für API B.
# Input (API A):
# {
# "userId": 123,
# "firstName": "Alice",
# "lastName": "Smith",
# "emailAddress": "alice@example.com"
# }
# Transform für API B:
jq '{
id: .userId,
name: (.firstName + " " + .lastName),
email: .emailAddress,
active: true
}' user-a.json
# Output (API B Format):
# {
# "id": 123,
# "name": "Alice Smith",
# "email": "alice@example.com",
# "active": true
# }
Zeit gespart: 10 Minuten vs. manuelles Umschreiben
Beispiel 5: Aggregate Sales-Data
Szenario: Orders.json, du willst Total-Revenue.
# Input:
# {
# "orders": [
# {"id": 1, "amount": 100, "status": "paid"},
# {"id": 2, "amount": 200, "status": "paid"},
# {"id": 3, "amount": 50, "status": "pending"}
# ]
# }
# Total Revenue (alle)
jq '[.orders[].amount] | add' orders.json
# 350
# Total Revenue (nur paid)
jq '[.orders[] | select(.status == "paid") | .amount] | add' orders.json
# 300
# Average Order Value
jq '[.orders[].amount] | add / length' orders.json
# 116.67
# Count by Status
jq '[.orders[]] | group_by(.status) | map({status: .[0].status, count: length})' orders.json
Produktivität: Business-Insights in Sekunden
Beispiel 6: Extract Emails von GitHub Contributors
Szenario: Repo-Contributors kontaktieren.
# 1. Get Contributors
curl -s api.github.com/repos/user/repo/contributors > contributors.json
# 2. Extract User-Logins
jq '.[].login' contributors.json
# 3. For each: Get Email (wenn public)
for login in $(jq -r '.[].login' contributors.json); do
email=$(curl -s "https://api.github.com/users/$login" | jq -r '.email // "N/A"')
echo "$login: $email"
done
# 4. Build Email-List
curl -s api.github.com/repos/user/repo/contributors \
| jq -r '.[].login' \
| xargs -I {} curl -s "https://api.github.com/users/{}" \
| jq -r 'select(.email != null) | .email'
Use-Case: Newsletter, Announcements
Claude Code Integration
Workflow 1: package.json Abhaengigkeiten analysieren
Bevor Claude Code neue Packages installiert oder Abhaengigkeiten aendert, willst du den aktuellen Stand kennen. Mit jq extrahierst du die Liste aller Dependencies und devDependencies, zahlst sie oder pruefst ob ein bestimmtes Package bereits installiert ist. Das ist schneller als die package.json manuell zu oeffnen und durchzuscrollen. Stell dir vor, du willst wissen ob React bereits als Dependency vorhanden ist bevor du Claude Code bittest es hinzuzufuegen - jq '.dependencies | has("react")' gibt dir sofort die Antwort.
# Claude Code Session: jq fuer JSON-Analyse
jq '.dependencies | keys' package.json
Workflow 2: API-Responses filtern
Wenn du mit httpie eine API-Response abrufst, enthaelt sie oft mehr Daten als du brauchst. Mit jq filterst du den Output auf die relevanten Felder und bekommst eine saubere, uebersichtliche Ausgabe. Das ist besonders nuetzlich um zu pruefen ob Claude Code's API-Implementation die richtigen Daten zurueckgibt. Stell dir vor, du testest einen User-Endpoint und willst nur Name und E-Mail sehen statt des gesamten User-Objekts mit 20 Feldern. Die Kombination von httpie und jq ist der schnellste Weg von "API-Call" zu "relevante Daten".
http GET api.example.com/users | jq '.[] | {name, email}'
Workflow 3: Config-Dateien transformieren
Manchmal musst du spezifische Eintraege aus Config-Dateien finden - zum Beispiel alle npm-Scripts die "test" im Befehl enthalten. jq's to_entries wandelt ein Objekt in ein Array von Key-Value-Paaren um, das du dann mit select() filtern kannst. Das ist nuetzlich um in grossen package.json-Dateien den Ueberblick zu behalten. Stell dir vor, du willst wissen welche npm-Scripts existieren die mit Testing zu tun haben - dieser Befehl findet sie alle. Das Ergebnis ist eine gefilterte Liste der relevanten Script-Eintraege.
jq '.scripts | to_entries | .[] | select(.value | contains("test"))' package.json
💡 Tipp: Claude Code kann jq-Queries generieren - beschreibe einfach welche Daten du aus dem JSON brauchst.
Video-Tutorial
[jq Tutorial - Offizielles Tutorial (jqlang.org)](https://jqlang.org/tutorial/) Das offizielle jq-Tutorial fuehrt dich Schritt fuer Schritt durch die wichtigsten Funktionen des JSON-Processors - vom Pretty-Print bis zu komplexen Filtern und Transformationen.
Troubleshooting
Problem: "parse error: Invalid numeric literal"
Dieser Fehler tritt auf, wenn der Input kein gueltiges JSON ist. Haeufige Ursachen sind fehlende Anfuehrungszeichen um Keys, einfache statt doppelte Anfuehrungszeichen, oder trailing Kommas. JSON ist strenger als JavaScript-Objekte - alle Keys muessen in doppelten Anfuehrungszeichen stehen. Stell dir vor, du kopierst ein JavaScript-Objekt {name: "Alice"} und piped es durch jq - das schlaegt fehl weil name nicht in Anfuehrungszeichen steht. Korrektes JSON waere {"name": "Alice"}. Pruefe deinen Input immer auf JSON-Konformitaet, zum Beispiel mit einem Online-Validator.
# JSON ungültig
echo '{name: "Alice"}' | jq '.' # FEHLER
# Fix: Proper JSON
echo '{"name": "Alice"}' | jq '.' # OK
Problem: "null Output (Field nicht gefunden)"
Wenn jq null zurueckgibt, existiert das abgefragte Feld nicht im JSON-Objekt. Das kann passieren wenn du einen Tippfehler im Feldnamen hast, das Feld optional ist, oder die Verschachtelung nicht stimmt. Statt einfach null anzuzeigen, kannst du mit dem Alternative-Operator // einen sinnvollen Default-Wert definieren. Stell dir vor, du verarbeitest User-Daten und manche User haben kein E-Mail-Feld - ohne Default-Wert bekommt dein Skript null und bricht moeglicherweise ab. Mit .email // "N/A" bekommst du stattdessen einen definierten Wert.
# Field existiert nicht
echo '{"name": "Alice"}' | jq '.email'
# null
# Safe Access (mit Default)
echo '{"name": "Alice"}' | jq '.email // "N/A"'
# "N/A"
Problem: "Output mit Quotes (fuer Scripts nervend)"
Standardmaessig gibt jq Strings mit JSON-konformen Anfuehrungszeichen aus (z.B. "Alice" statt Alice). In Shell-Skripten fuehrt das zu Problemen, weil die Anfuehrungszeichen Teil des Wertes werden. Der -r Flag (raw output) entfernt die Anfuehrungszeichen und gibt den reinen String-Wert aus. Stell dir vor, du extrahierst einen Wert und speicherst ihn in einer Shell-Variable - ohne -r enthaelt die Variable die Anfuehrungszeichen als Zeichen. Nutze -r immer dann wenn du jq-Output in Shell-Variablen, Loops oder anderen Befehlen verwendest.
# Mit Quotes (default)
jq '.name' user.json
# "Alice"
# Ohne Quotes (raw output)
jq -r '.name' user.json
# Alice
Problem: "Array-Iteration funktioniert nicht"
Ein haeufiger Anfaengerfehler ist der Unterschied zwischen .users und .users[]. Ohne die eckigen Klammern gibt jq das gesamte Array als einen einzelnen Wert zurueck - mit [] iteriert es ueber jedes Element einzeln. Stell dir vor, du willst den Namen jedes Users ausgeben und schreibst .users.name - das funktioniert nicht, weil .users ein Array ist und kein Objekt. Die korrekte Syntax ist .users[] | .name oder kurzform .users[].name. Dieser Unterschied ist fundamental fuer die Arbeit mit jq und sollte frueh verinnerlicht werden.
# FALSCH (gibt Array zurück)
jq '.users' data.json
# RICHTIG (iteriert über Items)
jq '.users[]' data.json
jq vs. grep vs. awk vs. Python - Der Vergleich
| Use-Case | jq | grep | awk | Python |
|----------|------|--------|-------|--------|
| JSON Pretty-Print | ✅ | ❌ | ❌ | ⚠️ Code |
| Extract JSON Fields | ✅ | ❌ | ❌ | ⚠️ Code |
| Filter JSON | ✅ | ⚠️ Basic | ⚠️ Basic | ✅ |
| Transform JSON | ✅ | ❌ | ⚠️ Hard | ✅ |
| Speed (Small Files) | 🚀 | 🚀 | 🚀 | 🐌 |
| Speed (Large Files) | 🚀 | 🚀 | 🚀 | 🐌 |
| Learning Curve | ⚠️ Medium | 🚀 Easy | 🐌 Steep | ⚠️ Medium |
Fazit:
jqfür JSON-Arbeit (unschlagbar)grepfür Simple Text-Searchawkfür Tabular Data- Python für komplexe Logik (wenn jq zu limitiert)
Weiterführende Links
Offizielle Ressourcen
- Website: https://jqlang.github.io/jq/
- Manual: https://jqlang.github.io/jq/manual/
- Playground: https://jqplay.org/ (Online-Tester)
Tutorials
- [jq Cheatsheet](https://devhints.io/jq)
- [jq Cookbook](https://github.com/stedolan/jq/wiki/Cookbook)
- [Advanced jq](https://programminghistorian.org/en/lessons/json-and-jq)
Community
- GitHub: https://github.com/jqlang/jq
- StackOverflow: [jq Tag](https://stackoverflow.com/questions/tagged/jq)
Pro-Tipps
. **jq in Vim/Neovim**
Wenn du JSON-Dateien in vim bearbeitest, ist das Formatieren ein haeufiger Schritt. Mit dem Befehl :%!jq '.' filterst du den gesamten Dateiinhalt durch jq und bekommst sauber formatiertes JSON zurueck. Das ist deutlich schneller als ein externes Tool zu oeffnen oder ein Plugin zu installieren. Stell dir vor, du oeffnest eine minifizierte JSON-Datei mit einer einzigen Zeile und 10.000 Zeichen - ein Befehl in vim und die Datei ist perfekt formatiert. Beachte, dass der Befehl die Datei in-place aendert - speichere vorher wenn du unsicher bist.
" Format JSON-File
:%!jq '.'
" Or: Command
:!jq '.' % > formatted.json && mv formatted.json %
. **Watch API with jq**
Mit dem watch-Befehl kannst du einen API-Endpoint regelmaessig abfragen und den Output formatiert anzeigen lassen. Das ist ideal fuer Live-Monitoring von API-Status-Endpoints, Deployment-Fortschritt oder Daten-Pipelines. watch -n 2 fuehrt den Befehl alle 2 Sekunden aus und aktualisiert die Anzeige. Stell dir vor, du deployst eine neue Version und willst den Status-Endpoint beobachten bis er "healthy" meldet - mit watch und jq siehst du die Aenderung in Echtzeit. Kombiniere das mit select() um nur relevante Aenderungen anzuzeigen.
# Live-Update alle 2 Sekunden
watch -n 2 'curl -s api.example.com/status | jq "."'
. **jq + fzf fuer interaktive Exploration**
Die Kombination von jq und fzf ermoeglicht interaktive JSON-Exploration. Du extrahierst die Keys eines JSON-Objekts, waehlst interaktiv einen Key mit fzf aus, und jq zeigt dir den Wert dieses Keys als Preview an. Das ist besonders nuetzlich bei grossen, unbekannten JSON-Strukturen, die du erst erkunden musst. Stell dir vor, du bekommst eine API-Response mit 50 Keys und willst herausfinden welcher die relevanten Daten enthaelt - mit fzf klickst du dich interaktiv durch. Die Preview-Funktion zeigt dir sofort den Inhalt jedes Keys an.
# Browse JSON-Keys
cat data.json | jq 'keys[]' | fzf --preview 'cat data.json | jq ".{}"'
. **Generate JSON (mit --null-input)**
Mit dem -n Flag (null-input) kann jq JSON generieren ohne einen Input zu benoetigen. Das ist nuetzlich fuer die Erstellung von Test-Daten, Config-Dateien oder API-Request-Bodies. Du kannst feste Werte, Shell-Variablen (ueber --arg) und dynamische Werte wie Timestamps kombinieren. Stell dir vor, du brauchst schnell eine Test-JSON-Datei mit User-Daten fuer einen API-Test - statt sie manuell in einem Editor zu erstellen, generierst du sie mit jq in einer Zeile. Das --arg-Flag erlaubt dir Shell-Variablen sicher in das JSON einzubetten, ohne Injection-Probleme.
# Empty Object
jq -n '{}'
# With Data
jq -n '{name: "Alice", age: 30, active: true}'
# Array
jq -n '[1,2,3,4,5]'
# From Variables
NAME="Alice"
jq -n --arg name "$NAME" '{name: $name, timestamp: now}'
Zusammenfassung
jq macht JSON-Processing trivial - unverzichtbar für API-Arbeit.
Quick Wins:
- ✅ Pretty-Print JSON (instant readability)
- ✅ Extract Fields (kein manuelles Parsing)
- ✅ Filter Arrays (nur relevante Items)
- ✅ Transform Data (für andere APIs)
Installation: 1 Minute Learning Curve: 15 Minuten (Basics), 2 Stunden (Mastery) Produktivität: +60% bei JSON-Arbeit
- [06 - httpie](./06-httpie.md) - HTTP Client (kombiniere mit jq)
- [19 - yq](./19-yq.md) - YAML Processor (ähnlich wie jq)
- [08 - gh](./08-gh.md) - GitHub CLI (nutzt JSON-APIs)