JSONPath Tutorial: Query JSON Like a Pro

Master JSONPath syntax with practical examples. Learn every operator, filter expression, and real-world query pattern to extract data from complex JSON structures.

JSONTech-TeamFebruary 1, 202511 min read

Was ist JSONPath?

JSONPath ist eine Abfragesprache für JSON – vergleichbar mit XPath für XML. Mit knapper Ausdruckssyntax greifen Sie in komplexe JSON-Strukturen und holen genau die Daten heraus, die Sie brauchen. Statt mit Schleifen und Bedingungen durch verschachtelte Objekte und Arrays zu navigieren, schreiben Sie einen einzigen Pfadausdruck wie $.store.book[?(@.price < 10)].title und erhalten alle Buchtitel unter zehn Dollar.

Stefan Goessner stellte JSONPath 2007 vor; seither hat es sich über Sprachen und Tools hinweg als De-facto-Standard etabliert. Arbeiten Sie mit REST-APIs, Konfigurationsdateien oder nicht trivialen JSON-Daten, spart Ihnen JSONPath erheblich Zeit.

JSONPath vs. XPath: Kurzvergleich

Kennen Sie XPath bereits, wirkt JSONPath vertraut. Entscheidend ist: JSON hat ein schlichteres Datenmodell – Objekte und Arrays statt Elemente, Attribute und Namespaces. So hängen die Konzepte zusammen:

KonzeptXPathJSONPath
Wurzel/$
Kindelement/child.child oder ['child']
Rekursiver Abstieg//..
Wildcard**
Array-Index[1] (1-basiert)[0] (0-basiert)
Filter[predicate][?(expression)]

Die vollständige JSONPath-Operatorreferenz

Jeder JSONPath-Ausdruck startet an der Wurzel $ und verkettet Operatoren zur Navigation. Dies sind die Operatoren, die Sie kennen sollten:

OperatorBeschreibungBeispiel
$Wurzelobjekt oder -array$ — das gesamte Dokument
.keyUntereigenschaft nach Name (Punktnotation)$.store.name
['key']Untereigenschaft nach Name (Klammernotation)$['store']['name']
..Rekursiver Abstieg — durchsucht alle Nachfahren$..price — jedes Feld price
*Wildcard — alle Member eines Objekts oder Arrays$.store.*
[n]Array-Index (0-basiert)$.items[0]
[start:end]Array-Slice (Ende exklusiv)$.items[0:3] — die ersten drei Elemente
[start:end:step]Array-Slice mit Schritt$.items[::2] — jedes zweite Element
[n,m]Mehrere Array-Indizes$.items[0,2,4]
[?()]Filterausdruck$.items[?(@.price > 10)]
@Aktueller Knoten (innerhalb von Filtern)@.name == 'Alice'

Beispiel-JSON für unsere Beispiele

Wir verwenden dieses JSON-Dokument durchgängig im Tutorial. Es stellt eine kompakte API-Antwort eines Buchladens dar:

{
  "store": {
    "name": "TechBooks Online",
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95,
        "inStock": true
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99,
        "inStock": false
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99,
        "inStock": true
      },
      {
        "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99,
        "inStock": true
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

Praktische JSONPath-Beispiele

1. Namen des Shops abrufen

$.store.name

Ergebnis:

"TechBooks Online"

2. Alle Buchtitel abrufen

$.store.book[*].title

Ergebnis:

[
  "Sayings of the Century",
  "Sword of Honour",
  "Moby Dick",
  "The Lord of the Rings"
]

3. Das erste Buch abrufen

$.store.book[0]

Ergebnis: das vollständige Objekt des ersten Buchs.

4. Das letzte Buch abrufen

$.store.book[-1]

Negative Indizes zählen vom Ende; -1 liefert das letzte Element.

5. Slice: die ersten zwei Bücher

$.store.book[0:2]

Liefert die Bücher an den Indizes 0 und 1. Der Endindex ist exklusiv – wie bei slice() in Python und JavaScript.

6. Alle Preise im gesamten Dokument

$..price

Ergebnis:

[8.95, 12.99, 8.99, 22.99, 19.95]

Der Operator für rekursiven Abstieg .. findet jedes Feld price unabhängig von der Tiefe – einschließlich des Fahrradpreises.

7. Filter: Bücher unter 10 $

$.store.book[?(@.price < 10)]

Liefert die beiden Bücher mit 8,95 und 8,99. Das Symbol @ bezeichnet das jeweils geprüfte Element.

8. Filter: Bücher mit ISBN

$.store.book[?(@.isbn)]

Liefert nur Moby Dick und The Lord of the Rings.

9. Filter: Fiction-Bücher auf Lager

$.store.book[?(@.category == 'fiction' && @.inStock == true)]

Bedingungen lassen sich mit && (UND) und || (ODER) verknüpfen.

10. Mehrere Indizes

$.store.book[0,3]

Gezielt einzelne Elemente wählen: erstes und viertes Buch.

11. Wildcard auf einem Objekt

$.store.bicycle.*

Ergebnis:

["red", 19.95]

Liefert alle Werte des Objekts bicycle.

12. Autoren teurer Bücher

$.store.book[?(@.price > 15)].author

Ergebnis:

["J. R. R. Tolkien"]

Probieren Sie es aus: Fügen Sie das Beispiel-JSON von oben ein und testen Sie diese Ausdrücke im JSONPath Tester von JSONTech.

Filterausdrücke im Detail

Filterausdrücke sind der stärkste Teil von JSONPath. Sie stehen in [?()] und werten für jedes Element eine boolesche Bedingung aus. Verfügbare Operatoren:

OperatorBedeutungBeispiel
==gleich@.status == 'active'
!=ungleich@.role != 'admin'
>größer als@.age > 18
>=größer oder gleich@.score >= 90
<kleiner als@.price < 50
<=kleiner oder gleich@.quantity <= 0
=~Regex-Übereinstimmung (implementationsabhängig)@.name =~ /^J.*/
&&logisches UND@.price > 5 && @.price < 20
``

Häufig prüft man, ob eine Eigenschaft existiert: @.isbn ohne Vergleichsoperator ist wahr, wenn die Eigenschaft vorhanden und nicht null ist.

Szenarien aus der Praxis

Alle E-Mail-Adressen aus einer API-Antwort extrahieren

Angenommen, eine Benutzerverwaltungs-API liefert tief verschachtelte Kontaktobjekte:

{
  "users": [
    {
      "name": "Alice",
      "contacts": { "email": "alice@example.com", "phone": "555-0101" }
    },
    {
      "name": "Bob",
      "contacts": { "email": "bob@example.com", "phone": "555-0102" }
    }
  ]
}

Abfrage: $..email

Ergebnis:

["alice@example.com", "bob@example.com"]

Rekursiver Abstieg findet jedes Feld email, unabhängig von der Position in der Hierarchie.

Produkte nach Preisspanne finden

$.products[?(@.price >= 25 && @.price <= 100)]

Praktisch, um API-Antworten clientseitig zu filtern, bevor eine Produktliste gerendert wird.

Verschachtelte Konfigurationswerte lesen

$.config.database.connections[0].host

Direkter Zugriff auf Konfigurationsdateien ohne verketteten optionalen Zugriff wie config?.database?.connections?.[0]?.host.

JSONPath in verschiedenen Sprachen

JavaScript / Node.js

Das Paket jsonpath-plus ist weit verbreitet:

import { JSONPath } from "jsonpath-plus";

const data = { store: { book: [{ title: "Moby Dick", price: 8.99 }] } };
const titles = JSONPath({ path: "$.store.book[*].title", json: data });
console.log(titles); // ["Moby Dick"]

Python

Mit jsonpath-ng erhalten Sie eine spezifikationsnahe Implementierung:

from jsonpath_ng.ext import parse

data = {"store": {"book": [{"title": "Moby Dick", "price": 8.99}]}}
expr = parse("$.store.book[*].title")
matches = [match.value for match in expr.find(data)]
print(matches)  # ['Moby Dick']

Java

Die Jayway-JSONPath-Bibliothek ist in JVM-Projekten üblich:

import com.jayway.jsonpath.JsonPath;

String json = "{\"store\":{\"book\":[{\"title\":\"Moby Dick\",\"price\":8.99}]}}";
List<String> titles = JsonPath.read(json, "$.store.book[*].title");
System.out.println(titles); // [Moby Dick]

Stolpersteine und Grenzen

JSONPath ist mächtig – dennoch sollten Sie Folgendes beachten, bevor Sie es produktiv einsetzen:

  • Lange keine formale Spezifikation. JSONPath war lange nur informell beschrieben; Bibliotheken unterschieden sich in Details. Die IETF veröffentlichte 2024 RFC 9535 zur Standardisierung der Syntax; viele Bibliotheken orientieren sich aber noch an Goessners Original. Prüfen Sie die Dokumentation Ihrer Bibliothek.
  • Regex-Support variiert. Der Operator =~ ist nicht überall verfügbar. Jayway unter Java unterstützt ihn; viele JavaScript-Bibliotheken nicht.
  • Keine Schreibzugriffe. JSONPath ist read-only. Das Quelldokument ändern Sie damit nicht; für Änderungen brauchen Sie JSON Patch (RFC 6902) oder manuelles Durchlaufen.
  • Performance bei sehr großen Dokumenten. Rekursiver Abstieg (..) besucht viele Knoten. Bei Millionen von Knoten kann das teuer werden – nutzen Sie dann möglichst spezifische Pfade.
  • Uneinheitliche Rückgabetypen. Manche Bibliotheken liefern bei einem Treffer einen Einzelwert, bei mehreren ein Array; andere immer ein Array. Normalisieren Sie den Rückgabewert in Ihrem Code.
  • Sonderzeichen in Schlüsseln. Enthalten Schlüssel Punkte, Leerzeichen oder andere Sonderzeichen, verwenden Sie Klammernotation: $('my.key') statt $.my.key.

JSONPath vs. jq

Wie verhält sich JSONPath zu jq, dem bekannten JSON-Prozessor für die Kommandozeile? Kurz: ähnliche Problemstellung, andere Zielgruppe.

  • JSONPath ist für die Einbettung in Anwendungscode gedacht, mit Bibliotheken in den gängigen Sprachen und einer gut lesbaren Abfragesyntax.
  • jq ist eine ausgewachsene Transformationssprache: filtern, mappen, reduzieren, Umformen von JSON. Mächtiger, steiler zu lernen, typisch für Shell und Pipelines.

Für Abfragen im Anwendungscode ist JSONPath pragmatisch; für Shell-Skripte und Datenpipelines ist jq schwer zu schlagen.

Schnellreferenz (Cheat Sheet)

ZielJSONPath
Gesamtes Dokument$
Bestimmte Eigenschaft$.user.name
Alle Array-Elemente$.items[*]
Erstes Element$.items[0]
Letztes Element$.items[-1]
Elementbereich$.items[1:4]
Jedes n-te Element$.items[::2]
Alle name-Felder überall$..name
Nach Wert filtern$.items[?(@.price < 10)]
Nach Existenz filtern$.items[?(@.discount)]
Mehrere Bedingungen$.items[?(@.qty > 0 && @.active)]

Probieren Sie es aus: Öffnen Sie den JSONPath Tester auf JSONTech.net und führen Sie Abfragen live gegen Ihre eigenen JSON-Daten aus.

Verwandte Tools