Filtrare JSON
Estrai solo le parti che ti servono con un’espressione di filtro JSONPath.
Nulla di ciò che incolli lascia il tuo browser. L’allowlist connect-src ne fa una garanzia del browser anziché una promessa. Verificalo tu stesso
Riduci un documento grande alla parte che ti serve, usando un’espressione di filtro JSONPath. Il risultato torna come array JSON dei valori corrispondenti, pronto da copiare.
Per essere chiari su che cos’è: è JSONPath, non jq. jq è un linguaggio completo e uno strumento davvero migliore per le trasformazioni complesse. Questo serve a selezionare, che è ciò che il filtraggio è quasi sempre.
Espressioni di filtro
Tutta la sintassi in un posto solo, visto che è la parte che si va a cercare ogni volta.
- $.items[?@.active]
- Ogni elemento in cui la chiave esiste ed è vera. La sola esistenza è già un test valido.
- $.items[?@.price < 10]
- Confronto numerico. L’ordinamento vale solo tra due numeri o tra due stringhe.
- $.items[?@.type == 'book']
- Confronto tra stringhe. Il literal va tra virgolette, ed è l’errore più comune.
- $.items[?@.price < 10 && @.stock > 0]
- Congiunzione con && e disgiunzione con ||, con raggruppamento tra parentesi.
- $.items[?!@.archived]
- Negazione, che qui significa chiave assente o falsa.
- $.items[?length(@.tags) > 2]
- Un’estensione di funzione. length() funziona su stringhe, array e oggetti.
- $.items[?match(@.sku, '[A-Z]{3}-[0-9]+')]
- Un’espressione regolare ancorata all’intero valore. Per una corrispondenza parziale usa search().
- $..[?@.id == 42]
- Un filtro applicato a ogni profondità: è così che trovi un record senza sapere dove si trova.
Che cosa succede a una chiave mancante
È il punto su cui le implementazioni pre-RFC divergevano di più, quindi vale la pena dirlo. Nella RFC 9535 una query che non seleziona nulla è «mancante», e un valore mancante è uguale soltanto a un altro valore mancante. Quindi @.price < 10 è falso quando price non c’è, invece di sollevare un errore o corrispondere. Perché un confronto con == sia vero, entrambi i membri devono essere mancanti.
Conseguenza pratica: per verificare l’assenza usa !@.price anziché @.price == null, perché null è un valore e l’assenza non lo è.
How to do this in code
Filtrare nel codice, dove di solito jq è la risposta giusta.
sh jq
Il terzo esempio è la riga che decide: se ti serve raggruppare o aggregare, usa jq.
# Select, then reshape
jq '[.items[] | select(.price < 10) | {sku, price}]' data.json
# Filter at any depth
jq '[.. | objects | select(.id? == 42)]' data.json
# Group and aggregate, which JSONPath cannot do at all
jq 'group_by(.category) | map({category: .[0].category, n: length})' data.json py Python
# A comprehension beats a query language for anything you
# can express directly.
cheap = [i for i in data['items'] if i['price'] < 10]
# JMESPath when the filter is configuration rather than code
import jmespath
cheap = jmespath.search("items[?price < `10`]", data) js JavaScript
const cheap = data.items.filter((i) => i.price < 10);
// Deep search without a library
function findAll(node, test, out = []) {
if (node && typeof node === 'object') {
if (test(node)) out.push(node);
for (const v of Object.values(node)) findAll(v, test, out);
}
return out;
}
const matches = findAll(data, (n) => n.id === 42); Domande frequenti
- Perché questo non è un playground di jq?
- Far girare jq davvero in un browser significa spedirlo compilato in WebAssembly, cioè circa un megabyte. Su un sito il cui argomento è che carica in fretta, è un pessimo scambio per uno strumento che la maggior parte delle persone usa per selezionare e non per trasformare. Inoltre chiamare «playground di jq» un filtro JSONPath sarebbe una bugia, e questo sito non lo fa.
- Posso filtrare e rimodellare allo stesso tempo?
- Con JSONPath no: seleziona nodi, non ne costruisce di nuovi. Usa JMESPath, che ha i multiselect hash, oppure jq.
- Come trovo ogni oggetto con una certa chiave ovunque nel documento?
- $..[?@.laChiave] applica il filtro a ogni profondità. Per trovare un record preciso, $..[?@.id == 42].