JSON filtern
Holen Sie mit einem JSONPath-Filterausdruck nur die Teile heraus, die Sie brauchen.
Nichts, was Sie einfügen, verlässt Ihren Browser. Die connect-src Erlaubnisliste macht daraus eine Garantie des Browsers statt eines Versprechens. Selbst überprüfen
Kürzen Sie ein großes Dokument mit einem JSONPath-Filterausdruck auf den Teil, den Sie brauchen. Das Ergebnis kommt als JSON-Array der passenden Werte zurück, fertig zum Kopieren.
Damit klar ist, was das hier ist: Es ist JSONPath, nicht jq. jq ist eine vollwertige Sprache und für komplexe Transformationen tatsächlich das bessere Werkzeug. Hier geht es um Auswahl, und das ist es, was Filtern meistens wirklich bedeutet.
Filterausdrücke
Die ganze Syntax an einem Ort, weil das der Teil ist, den man jedes Mal nachschlägt.
- $.items[?@.active]
- Jedes Element, bei dem der Schlüssel existiert und wahr ist. Bloße Existenz ist ein gültiger Test.
- $.items[?@.price < 10]
- Numerischer Vergleich. Ordnung gilt nur zwischen zwei Zahlen oder zwei Zeichenketten.
- $.items[?@.type == 'book']
- Zeichenkettenvergleich. Das Literal muss in Anführungszeichen stehen - der häufigste Fehler.
- $.items[?@.price < 10 && @.stock > 0]
- Konjunktion mit && und Disjunktion mit ||, Gruppierung mit Klammern.
- $.items[?!@.archived]
- Negation, was hier heißt: Der Schlüssel fehlt oder ist falsch.
- $.items[?length(@.tags) > 2]
- Eine Funktionserweiterung. length() arbeitet auf Zeichenketten, Arrays und Objekten.
- $.items[?match(@.sku, '[A-Z]{3}-[0-9]+')]
- Ein regulärer Ausdruck, verankert am gesamten Wert. Für einen Teiltreffer nehmen Sie search().
- $..[?@.id == 42]
- Ein Filter, der auf jeder Ebene angewendet wird - so finden Sie einen Datensatz, ohne zu wissen, wo er liegt.
Was mit einem fehlenden Schlüssel passiert
Hier gingen die Implementierungen vor der RFC am weitesten auseinander, deshalb sei es ausgesprochen. In RFC 9535 ist eine Abfrage, die nichts auswählt, „fehlend“, und ein fehlender Wert ist nur einem anderen fehlenden Wert gleich. @.price < 10 ist also falsch, wenn price nicht da ist, statt zu werfen oder zu treffen. Damit ein ==-Vergleich wahr ist, müssen beide Seiten fehlend sein.
Praktische Folge: Um auf Abwesenheit zu prüfen, nehmen Sie !@.price statt @.price == null, denn null ist ein Wert und Abwesenheit ist keiner.
How to do this in code
Filtern im Code - wo jq meistens die richtige Antwort ist.
sh jq
Das dritte Beispiel ist die Zeile, die entscheidet: Wenn Sie gruppieren oder aggregieren müssen, nehmen Sie 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); Häufige Fragen
- Warum ist das kein jq-Playground?
- Echtes jq im Browser laufen zu lassen heißt, es nach WebAssembly kompiliert auszuliefern - rund ein Megabyte. Auf einer Seite, deren Argument schnelles Laden ist, ist das ein schlechter Handel für ein Werkzeug, das die meisten zum Auswählen und nicht zum Transformieren benutzen. Einen JSONPath-Filter als jq-Playground zu bezeichnen wäre außerdem gelogen, und das macht diese Seite nicht.
- Kann ich gleichzeitig filtern und umformen?
- Mit JSONPath nicht: Es wählt Knoten aus, es baut keine neuen. Nehmen Sie JMESPath mit seinen Multiselect-Hashes, oder jq.
- Wie finde ich jedes Objekt mit einem bestimmten Schlüssel irgendwo im Dokument?
- $..[?@.derSchlüssel] wendet den Filter auf jeder Ebene an. Für einen bestimmten Datensatz: $..[?@.id == 42].