Skip to content
Torna al blog
Tutorial

jq Cheat Sheet: 30 pattern JSON da riga di comando reali

Padroneggia jq online con 30 pattern collaudati per filtrare, trasformare ed estrarre JSON da riga di comando — da kubectl e AWS ai file di log.

12 min di lettura

jq Cheat Sheet: 30 pattern JSON da riga di comando reali

Lanci kubectl get pods -o json in pipe verso less e il terminale si blocca davanti a un muro di JSON da due megabyte. Tutto ciò che vuoi è il nome di ogni pod nella fase Running. jq lo fa con tre caratteri di sintassi del filtro — una volta che conosci il vocabolario.

Questa non è una guida di riferimento sulla sintassi. Sono 30 pattern che digiterai davvero, raggruppati per attività che stai cercando di realizzare: accesso, filtraggio, trasformazione, aggregazione, formattazione e collegamento con strumenti reali come kubectl, aws e docker.

Quando usare jq vs un formattatore nel browser vs codice

jq non è sempre la risposta giusta. Le tre scelte oneste sono queste:

SituazioneStrumento migliorePerché
Una risposta API, serve evidenziazione sintassi e numeri di riga erroreFormattatore JSON nel browserDiff visivo, zero setup, privato nel browser
Pipeline shell, elaborazione log, script CI, server remotojqComponibile, scriptabile, nessuna dipendenza GUI
Logica di business, unit test, branching complessoCodice in linguaggio (JS / Python)Debugger reale, tipi, librerie

Scegli jq quando il task vive dentro una pipeline shell — tutto il resto è probabilmente più facile altrove.

Installazione e la tua prima pipeline

jq è distribuito come singolo binario su ogni piattaforma principale:

# macOS
brew install jq

# Debian / Ubuntu
sudo apt install jq

# Windows (winget)
winget install jqlang.jq

Una prima pipeline, con il filtro identità:

curl -s https://api.github.com/users/octocat | jq .

Il filtro . prende il suo input ed emette inalterato, formattato in modo leggibile. Solo questo sostituisce la maggior parte dei momenti “fammi aprire questo JSON in un editor”.

Cinque flag coprono il 90% dell’uso reale:

FlagScopo
-rOutput raw — rimuove le virgolette circostanti dai risultati stringa
-cCompatto — un valore JSON per riga (NDJSON)
-sSlurp — legge tutti gli input in un singolo array
-RInput raw — legge le righe come stringhe invece che JSON
-nInput null — non legge stdin, usa null come input

Il modello mentale di base: filtri e pipe

Un filtro prende un valore JSON come input e produce zero o più valori JSON come output. I filtri si compongono con un pipe |, che invia ogni output del filtro a sinistra come input al filtro a destra. Questo è lo stesso modello mentale dei pipe shell, solo con valori JSON che fluiscono invece che byte.

# . — identità
echo '{"name":"Alice"}' | jq '.'

# .key — accesso al campo
echo '{"name":"Alice"}' | jq '.name'

# .key.sub — percorso profondo
echo '{"user":{"email":"a@x.com"}}' | jq '.user.email'

# .[] — itera elementi array (produce output multipli)
echo '[{"id":1},{"id":2}]' | jq '.[] | .id'

# Composizione pipe: ogni output di .items[] alimenta .name
echo '{"items":[{"name":"a"},{"name":"b"}]}' | jq '.items[] | .name'

Questa è tutta la grammatica. I 30 pattern qui sotto sono combinazioni di queste primitive.

30 pattern che userai davvero

Ogni pattern mostra il JSON di input, il comando e l’output. Copia uno qualsiasi di essi nel tuo terminale.

Accesso ed estrazione (pattern 1–5)

Pattern 1 — Accesso sicuro con ?

Accedi a un campo che potrebbe non esistere senza crashare:

echo '{"name":"Alice"}' | jq '.address?.city?'
# Output: null

Il ? sopprime gli errori sulle chiavi mancanti. Senza, .address.city lancerebbe un errore di tipo se .address è assente.

Pattern 2 — Accesso a percorso profondo

echo '{"user":{"profile":{"email":"a@x.com"}}}' | jq '.user.profile.email'
# Output: "a@x.com"

Pattern 3 — Slicing di array

echo '[10,20,30,40,50]' | jq '.[1:3]'
# Output: [20, 30]

echo '[10,20,30,40,50]' | jq '.[-1]'
# Output: 50

Gli indici negativi contano dalla fine. Le slice usano intervalli semi-aperti, come Python.

Pattern 4 — Discesa ricorsiva per trovare ogni chiave corrispondente

echo '{"a":{"name":"x"},"b":[{"name":"y"},{"id":1}]}' | jq '.. | .name? | select(. != null)'
# Output: "x"
#         "y"

.. percorre ogni valore nell’albero. Combinato con .name? e select, estrae ogni campo name indipendentemente dalla profondità — preziosissimo per esplorare schemi JSON sconosciuti.

Pattern 5 — Elenca tutte le chiavi di un oggetto

echo '{"zebra":1,"apple":2,"mango":3}' | jq 'keys'
# Output: ["apple", "mango", "zebra"]

echo '{"zebra":1,"apple":2,"mango":3}' | jq 'keys_unsorted'
# Output: ["zebra", "apple", "mango"]

keys ordina alfabeticamente; keys_unsorted preserva l’ordine di inserimento.

Filtraggio (pattern 6–10)

Pattern 6 — Filtra un array per condizione

echo '[{"age":20},{"age":30},{"age":40}]' | jq 'map(select(.age > 25))'
# Output: [{"age":30},{"age":40}]

map(f) applica f a ciascun elemento; select(cond) mantiene solo gli elementi dove la condizione è vera.

Pattern 7 — Corrispondenza prefisso stringa

echo '[{"name":"api-gateway"},{"name":"web-ui"},{"name":"api-auth"}]' \
  | jq '.[] | select(.name | startswith("api"))'
# Output: {"name":"api-gateway"}
#         {"name":"api-auth"}

Anche utili: endswith("..."), contains("..."), test("^regex$").

Pattern 8 — Condizioni combinate

echo '[{"type":"A","count":5},{"type":"A","count":15},{"type":"B","count":20}]' \
  | jq '.[] | select(.type == "A" and .count > 10)'
# Output: {"type":"A","count":15}

and, or, not funzionano come ti aspetti.

Pattern 9 — Elimina campi sensibili

echo '{"user":"alice","password":"s3cret","token":"abc"}' | jq 'del(.password, .token)'
# Output: {"user":"alice"}

del() accetta percorsi multipli ed è sicuro se uno qualsiasi è mancante.

Pattern 10 — Deduplica per campo

echo '[{"id":1,"v":"a"},{"id":2,"v":"b"},{"id":1,"v":"a2"}]' | jq 'unique_by(.id)'
# Output: [{"id":1,"v":"a"},{"id":2,"v":"b"}]

unique deduplica valori interi; unique_by(f) deduplica per il risultato di un filtro.

Trasformazione (pattern 11–15)

Pattern 11 — Rinomina campi

echo '[{"first_name":"Alice","age":30}]' | jq 'map({name: .first_name, age})'
# Output: [{"name":"Alice","age":30}]

La forma abbreviata {age} è equivalente a {age: .age}.

Pattern 12 — Aggiungi un campo calcolato con interpolazione di stringa

echo '[{"first":"Alice","last":"Chen"}]' \
  | jq 'map(. + {fullName: "\(.first) \(.last)"})'
# Output: [{"first":"Alice","last":"Chen","fullName":"Alice Chen"}]

\(expr) valuta expr e ne interpola il valore nella stringa.

Pattern 13 — Appiattisci array annidati

echo '[{"tags":["a","b"]},{"tags":["c"]}]' | jq '[.[] | .tags[]]'
# Output: ["a","b","c"]

echo '[[1,2],[3,[4,5]]]' | jq 'flatten'
# Output: [1,2,3,4,5]

flatten accetta un argomento di profondità opzionale: flatten(1) rimuove un solo livello.

Pattern 14 — Da oggetto ad array e ritorno

echo '{"a":1,"b":2}' | jq 'to_entries'
# Output: [{"key":"a","value":1},{"key":"b","value":2}]

echo '[{"key":"a","value":1},{"key":"b","value":2}]' | jq 'from_entries'
# Output: {"a":1,"b":2}

Questa coppia abilita trasformazioni che richiedono di iterare sulle chiavi dell’oggetto — qualcosa che la sintassi a percorso col punto non può fare direttamente.

Pattern 15 — Deep-merge di due oggetti

echo '{"a":{"x":1},"b":2}' | jq '. * {a:{y:9}, c:3}'
# Output: {"a":{"x":1,"y":9},"b":2,"c":3}

L’operatore * esegue il deep-merge. Per il merge superficiale, usa + (vince il lato destro).

Aggregazione (pattern 16–20)

Pattern 16 — Lunghezza di array, oggetti e stringhe

echo '[1,2,3,4]' | jq 'length'      # 4
echo '{"a":1,"b":2}' | jq 'length'  # 2
echo '"hello"' | jq 'length'        # 5

Pattern 17 — Somma un campo

echo '[{"price":10},{"price":25},{"price":5}]' | jq '[.[].price] | add'
# Output: 40

add somma numeri, concatena stringhe o unisce array — a seconda del tipo di input.

Pattern 18 — Raggruppa per campo

echo '[{"cat":"A","n":1},{"cat":"B","n":2},{"cat":"A","n":3}]' | jq 'group_by(.cat)'
# Output: [[{"cat":"A","n":1},{"cat":"A","n":3}],[{"cat":"B","n":2}]]

Ogni gruppo diventa un array interno. Combina con map per aggregare per gruppo.

Pattern 19 — Ordina in ordine decrescente

echo '[{"date":"2026-01-03"},{"date":"2026-01-01"},{"date":"2026-01-02"}]' \
  | jq 'sort_by(.date) | reverse'
# Output: [{"date":"2026-01-03"},{"date":"2026-01-02"},{"date":"2026-01-01"}]

Le stringhe di data ISO 8601 si ordinano correttamente come stringhe. Per altri formati, fai prima il parsing — la guida ai timestamp Unix copre in profondità secondi epoch, millisecondi e conversione di fuso orario.

Pattern 20 — Max o min per campo

echo '[{"name":"a","rating":4.1},{"name":"b","rating":4.8},{"name":"c","rating":3.9}]' \
  | jq 'max_by(.rating)'
# Output: {"name":"b","rating":4.8}

min_by, max_by restituiscono un singolo elemento. Per i top N, usa sort_by(.rating) | reverse | .[:N].

Formattare l’output (pattern 21–25)

Pattern 21 — Output CSV

echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' \
  | jq -r '.[] | [.name, .age] | @csv'
# Output: "Alice",30
#         "Bob",25

@csv mette tra virgolette le stringhe e fa l’escape delle virgolette al loro interno. -r rimuove le virgolette esterne della stringa JSON così il CSV è direttamente convogliabile in pipe. Per il giro completo tra CSV e JSON nelle pipeline, vedi la guida alla conversione CSV verso JSON.

Pattern 22 — Output TSV

echo '[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]' \
  | jq -r '.[] | [.id, .name] | @tsv'
# Output: 1	Alice
#         2	Bob

L’output separato da tab si sposa bene con cut, awk e column -t.

Pattern 23 — Output stringa raw

echo '["alpha","beta"]' | jq -r '.[]'
# Output: alpha
#         beta

Senza -r, ogni riga avrebbe le virgolette circostanti. L’output raw è ciò che dai in pasto a xargs, while read o un altro comando shell.

Pattern 24 — NDJSON / JSON Lines

echo '[{"a":1},{"a":2}]' | jq -c '.[]'
# Output: {"a":1}
#         {"a":2}

Ogni riga è un valore JSON autonomo — il formato usato da Kafka, Elasticsearch e dalla maggior parte dei logger strutturati. -c rimuove anche tutti gli spazi bianchi interni.

Pattern 25 — Interpolazione di stringa per output formattato

echo '[{"name":"server-1","cpu":0.73},{"name":"server-2","cpu":0.21}]' \
  | jq -r '.[] | "\(.name): \(.cpu * 100)% CPU"'
# Output: server-1: 73% CPU
#         server-2: 21% CPU

Ottimo per riassunti e righe di log dove il JSON raw sarebbe rumore.

DevOps sul campo (pattern 26–30)

Pattern 26 — kubectl: nomi di ogni pod in esecuzione

kubectl get pods -o json \
  | jq -r '.items[] | select(.status.phase=="Running") | .metadata.name'

Pipeline: itera i pod, mantieni solo Running, emetti il nome come stringa raw.

Pattern 27 — AWS EC2: ID istanza con IP pubblici

aws ec2 describe-instances \
  | jq -r '.Reservations[].Instances[] | [.InstanceId, .PublicIpAddress // "none"] | @tsv'

L’operatore alternativo // fornisce un fallback quando il campo è null — evitando un letterale null nella colonna di output.

Pattern 28 — API GitHub: unisci risultati paginati

for p in 1 2 3; do
  curl -s "https://api.github.com/orgs/myorg/repos?per_page=100&page=$p"
done | jq -s 'add | map(.name)'

-s slurp tutte le risposte in un array di array, add le concatena, poi map(.name) estrae i nomi. Un pattern comune per qualsiasi API paginata.

Pattern 29 — Filtra file di log strutturati

cat app.log | jq -c 'select(.level=="error")'

Si assume che il file di log sia NDJSON (un oggetto JSON per riga). Abbinalo a tail -f per monitoraggio live:

tail -f app.log | jq -c 'select(.level=="error") | {ts: .timestamp, msg: .message}'

Pattern 30 — Docker: tutti i nomi delle immagini in uso

docker inspect $(docker ps -q) | jq -r '.[].Config.Image' | sort -u

Buono per verificare velocemente quali versioni di immagini stanno girando su un host.

Errori comuni e come risolverli

Ogni utente di jq incappa in questi. Conoscere la soluzione in anticipo fa risparmiare ore.

Cannot iterate over null (null)

Il campo di input che hai provato a iterare era null o mancante. Due soluzioni:

# Opzione A: operatore opzionale
echo '{}' | jq '.items[]?'
# Output: (niente, nessun errore)

# Opzione B: operatore alternativo con default
echo '{}' | jq '(.items // [])[]'
# Output: (niente, nessun errore)

Usa ? quando vuoi saltare in silenzio. Usa // [] quando vuoi forzare un array vuoto concreto in modo che i filtri a valle continuino a girare.

Cannot index array with "key"

Hai scritto .foo ma il valore corrente è un array. Aggiungi [] per iterare:

# Sbagliato
echo '{"users":[{"name":"Alice"}]}' | jq '.users.name'
# Errore: Cannot index array with "name"

# Giusto
echo '{"users":[{"name":"Alice"}]}' | jq '.users[].name'
# Output: "Alice"

Problemi di quoting nella shell

Usa virgolette singole attorno all’intero programma jq, virgolette doppie all’interno per i letterali stringa:

# Funziona ovunque
jq '.users[] | select(.role == "admin")'

# Si rompe — virgolette doppie interpretate prima dalla shell
jq ".users[] | select(.role == \"admin\")"

Casi limite con Windows PowerShell

PowerShell non tratta le virgolette singole allo stesso modo. Preferisci virgolette doppie attorno al programma e fai l’escape delle virgolette interne, o usa una here-string:

jq "@'
.users[] | select(.role == \"admin\")
'@"

Per qualsiasi cosa non banale, salva il filtro in un file .jq ed esegui jq -f filter.jq.

Uso scorretto dell’output raw

-r influenza solo i risultati stringa. Dargli un oggetto produce un normale oggetto JSON:

echo '{"a":1}' | jq -r '.'
# Output: {"a":1}     ← invariato; -r non aveva niente da rimuovere

Se vuoi un campo specifico senza virgolette, selezionalo prima: jq -r '.a'.

jq rifiuta JSON con commenti o virgole finali

echo '{"a": 1, /* note */ "b": 2,}' | jq .
# parse error: Invalid numeric literal

jq segue lo stretto JSON RFC 8259 — niente commenti, niente virgole finali, nessuna chiave senza virgolette. Se il file è JSON5 o JSONC (comune per i file di configurazione), rimuovi prima le estensioni. La guida alla formattazione JSON5 e JSONC copre quali parser li gestiscono e come convertirli a JSON stretto prima di passarli in pipe a jq.

jq vs alternative: gron, fx, jj, yq

jq non è l’unica opzione, e a volte uno strumento diverso è più veloce:

StrumentoPunto di forzaQuando ricorrervi
gronAppiattisce JSON in percorsi grep-abiliEsplorare schemi sconosciuti — non sai dov’è la chiave
fxEsploratore TUI interattivo con evidenziazioneSfogliare a mano JSON di grandi dimensioni
jjMolto più veloce di jq, sintassi limitataLoop caldi che processano milioni di record
yqStesso linguaggio di filtri ma per YAMLManifest Kubernetes e config CI
Formattatore JSON nel browserEvidenziazione sintassi, messaggi di errore precisi, zero installazioneDebug di una singola risposta durante lo sviluppo

Per il lavoro shell quotidiano, jq vince per componibilità. Per esplorazioni una tantum, gron è spesso più veloce. Per YAML, usa yq — non provare a fare pipe attraverso yq-poi-jq.

Pro tip per l’uso quotidiano

Alcune abitudini che rendono jq familiare:

  1. Tieni un .jqrc in $HOME. Inserisci lì le funzioni helper, e saranno disponibili in ogni invocazione di jq:

    def running: select(.status.phase == "Running");
    def table(f): [f] | @tsv;
  2. Usa jqplay.org per filtri complessi. Incolla il tuo JSON a sinistra, itera il filtro a destra, spedisci la versione funzionante nel tuo script.

  3. Costruisci il tuo cheat sheet da history. history | grep 'jq ' | sort -u > ~/jq-patterns.txt cattura ogni pattern che hai effettivamente usato.

  4. Combina con il Formattatore JSON nel browser per schemi sconosciuti. Esplora prima la struttura visivamente per trovare il percorso che ti serve, poi scrivi il comando jq.

  5. Osserva valori in tempo reale: watch -n 5 "curl -s api.example.com/health | jq '.uptime'" aggiorna ogni 5 secondi — una rapida dashboard ops senza dipendenze.

FAQ

Cos’è jq e perché gli sviluppatori lo usano?

jq è un processore JSON da riga di comando. Estrae, filtra e trasforma JSON dentro pipeline shell senza uno script Python o Node — il percorso più veloce dalle risposte API, file di log o output di kubectl al campo che vuoi davvero.

jq è disponibile su Windows?

Sì. Installa via winget install jqlang.jq, Chocolatey choco install jq, o scarica il binario da jqlang.org. Le regole di quoting di PowerShell differiscono da bash — quando in dubbio, salva i filtri in un file .jq ed esegui jq -f filter.jq.

In cosa differisce jq da un formattatore JSON nel browser?

Un Formattatore JSON nel browser è interattivo — incolli JSON, vedi evidenziazione ed errori, copi il risultato. jq non è interattivo — descrivi la trasformazione una volta, la esegui attraverso una pipeline shell. Usa il browser per fare debug di una risposta; usa jq per automatizzare la stessa operazione su centinaia.

Perché jq dice “Cannot iterate over null”?

Hai provato a iterare (.[]) su un valore che è null — di solito perché il campo era mancante dall’input. Risolvi con l’operatore opzionale .items[]? o fornisci un default con .items // [] | .[].

jq può modificare i file in place?

Non direttamente — jq scrive su stdout. Usa un file temporaneo o sponge da moreutils: jq '.version = "2.0"' config.json | sponge config.json. Fai sempre prima un backup dell’originale; un filtro con un refuso sovrascriverà il file.

Come uso jq con risposte curl?

Passa curl -s in pipe a jq. Il flag -s silenzia il misuratore di progresso di curl così solo il corpo JSON raggiunge jq:

curl -s https://api.github.com/users/octocat | jq '.name, .blog'

Qual è la differenza tra il | di jq e il | della shell?

Il pipe shell invia byte tra processi. Il pipe di jq invia valori JSON tra filtri dentro un’unica invocazione di jq. Un singolo comando jq con molti pipe interni gira in un processo solo — più economico che concatenare jq | jq | jq.

jq può gestire JSON Lines (NDJSON)?

Sì, nativamente. jq legge ogni riga come un valore JSON indipendente quando sono separate da spazi bianchi. Usa -c per emettere NDJSON e -s per raccogliere NDJSON in un singolo array.

Come formatto JSON in modo leggibile senza filtrare?

Usa il filtro identità: cat data.json | jq . o semplicemente jq . < data.json. Fa il parsing, valida e formatta in modo leggibile con rientro a due spazi — nessun filtro richiesto.

Esiste un’alternativa a jq con una GUI?

Sì. fx fornisce una TUI interattiva. Per una GUI senza installazione, il Formattatore JSON basato su browser copre la maggior parte delle esigenze esplora-e-valida. Strumenti web come jqplay.org offrono jq stesso con anteprima live.

Quando dovrei usare jq invece di scrivere uno script Python?

Ricorri a jq quando il task è una tantum, sta in una pipeline shell e rimane dentro la semantica di filtro, trasformazione ed estrazione. Passa a Python quando ti servono unit test, stato complesso, librerie di terze parti o logica di branching oltre quanto un file .jq mantenga leggibile.

Come uso le espressioni regolari in jq?

jq espone regex via test("pattern"), match("pattern"), capture("pattern") e scan("pattern"), tutte usando sintassi PCRE. Passa flag come secondo argomento: test("abc"; "i") per case-insensitive. match restituisce offset e cattura; scan emette ogni match non sovrapposto.

Punti chiave

  1. Prima il modello mentale: filtro in entrata, zero o più valori JSON in uscita, componi con |. Tutto il resto è sintassi.
  2. Impara per task, non per operatore: i 30 pattern qui sopra coprono circa il 95% dell’uso quotidiano di jq.
  3. Gestisci null esplicitamente: ? per saltare in silenzio, // default per fallback concreto. La maggior parte delle correzioni Cannot iterate over null è una di queste due.
  4. Sappi quando jq è lo strumento sbagliato: le singole risposte appartengono a un Formattatore JSON nel browser; YAML appartiene a yq; la logica complessa appartiene al codice vero.
  5. Abbinalo al tuo stack esistente: jq brilla dentro curl, kubectl, aws, docker e pipeline di log. Usalo come collante, non come livello logico.

Per workflow JSON correlati, vedi la guida alla formattazione JSON5 e JSONC per le estensioni di sintassi dei file di configurazione, e la guida alla conversione CSV verso JSON per migrazioni di formato dati dove jq si inserisce nella pipeline. Quando il tuo JSON contiene timestamp, la guida ai timestamp Unix copre le insidie che incontrerai trasformando i campi data.

Articoli correlati

Vedi tutti gli articoli