JSONPath Cheatsheet: Cara Query dan Filter Data JSON Nested
Kalau kamu pernah kerja dengan response API yang isinya JSON bertingkat-tingkat — array di dalam object, object di dalam array, sampai lima enam level ke dalam — pasti pernah merasa capek scroll manual cuma buat cari satu field. Di sinilah JSONPath berguna. JSONPath adalah bahasa query khusus untuk JSON, mirip seperti XPath untuk XML, yang memungkinkan kamu mengambil (extract) atau memfilter data dari struktur JSON yang kompleks hanya dengan satu baris ekspresi.
Artikel ini adalah cheatsheet praktis: kumpulan sintaks JSONPath paling sering dipakai, lengkap dengan contoh data dan hasil query-nya, supaya kamu bisa langsung copy-paste dan sesuaikan dengan kebutuhan sendiri.
Apa itu JSONPath?
JSONPath pertama kali dipopulerkan oleh Stefan Gössner pada 2007 sebagai cara untuk menavigasi dokumen JSON secara deklaratif. Sekarang JSONPath dipakai di banyak tools — dari library pemrograman (Python jsonpath-ng, JavaScript jsonpath-plus), API gateway, hingga tools observability seperti Grafana dan Postman yang punya fitur "extract variable from response" berbasis JSONPath.
Konsep dasarnya: kamu mulai dari root dokumen (dilambangkan $), lalu "turun" ke property atau elemen array menggunakan notasi titik atau kurung siku, mirip cara kamu mengakses object di JavaScript.
Data Contoh untuk Cheatsheet Ini
Supaya konsisten, semua contoh di bawah memakai data JSON berikut — sebuah toko buku dengan daftar buku dan info toko:
{
"store": {
"name": "Toko Buku Nusantara",
"location": "Jakarta",
"books": [
{ "title": "Laskar Pelangi", "author": "Andrea Hirata", "price": 55000, "category": "fiction", "stock": 12 },
{ "title": "Bumi Manusia", "author": "Pramoedya Ananta Toer", "price": 68000, "category": "fiction", "stock": 0 },
{ "title": "Filosofi Teras", "author": "Henry Manampiring", "price": 89000, "category": "nonfiction", "stock": 30 },
{ "title": "Sapiens", "author": "Yuval Noah Harari", "price": 120000, "category": "nonfiction", "stock": 5 }
]
}
}
Sintaks Dasar JSONPath
$— root dari dokumen JSON.— child operator, mengakses property secara langsung[]— bracket notation, alternatif dari dot operator, wajib dipakai kalau nama property mengandung spasi atau karakter khusus*— wildcard, artinya "semua elemen" pada level tersebut..— recursive descent, mencari di semua level tanpa peduli kedalaman[n]— mengakses elemen array pada index ke-n (dimulai dari 0)[start:end]— array slice, mengambil rentang elemen[?(expression)]— filter expression, mengambil elemen yang memenuhi kondisi[,]— union, memilih beberapa index atau nama sekaligus
Contoh Query Dasar
Mengambil nama toko (root → child → child):
$.store.name
// hasil: "Toko Buku Nusantara"
Mengambil semua judul buku menggunakan wildcard:
$.store.books[*].title
// hasil: ["Laskar Pelangi", "Bumi Manusia", "Filosofi Teras", "Sapiens"]
Mengambil buku pertama dalam array (index dimulai dari 0):
$.store.books[0]
// hasil: { "title": "Laskar Pelangi", "author": "Andrea Hirata", ... }
Mengambil dua buku pertama menggunakan array slice:
$.store.books[0:2]
// hasil: [Laskar Pelangi, Bumi Manusia]
Mengambil buku terakhir menggunakan negative index (didukung sebagian besar implementasi):
$.store.books[-1:]
// hasil: [Sapiens]
Recursive Descent: Cari di Semua Level
Operator .. sangat berguna kalau kamu tidak tahu persis di level mana sebuah field berada, atau field itu muncul berkali-kali di kedalaman berbeda. Misalnya, mengambil semua nilai price di manapun posisinya:
$..price
// hasil: [55000, 68000, 89000, 120000]
Ini setara dengan "cari field bernama price, di mana saja, seberapa dalam pun" — sangat berguna untuk payload API yang strukturnya tidak konsisten antar versi.
Filter Expression: Query dengan Kondisi
Bagian paling powerful dari JSONPath adalah filter expression [?(...)], yang memungkinkan kamu memfilter array berdasarkan kondisi tertentu — mirip klausa WHERE di SQL.
Mengambil semua buku dengan harga di atas 60000:
$.store.books[?(@.price > 60000)]
// hasil: Bumi Manusia, Filosofi Teras, Sapiens
Simbol @ di sini merujuk ke elemen yang sedang diproses (current node), berbeda dengan $ yang selalu merujuk ke root.
Mengambil buku kategori fiction yang stoknya habis:
$.store.books[?(@.category == 'fiction' && @.stock == 0)]
// hasil: Bumi Manusia
Mengambil hanya judul dari buku yang harganya di bawah 90000:
$.store.books[?(@.price < 90000)].title
// hasil: ["Laskar Pelangi", "Bumi Manusia", "Filosofi Teras"]
Union: Pilih Beberapa Sekaligus
Kalau kamu butuh beberapa index atau nama property tertentu saja, gunakan koma sebagai union operator:
$.store.books[0,2].title
// hasil: ["Laskar Pelangi", "Filosofi Teras"]
Tabel Ringkas Cheatsheet
$→ root dokumen$.a.b→ child property berantai$.a[*]→ semua elemen array a$..a→ cari property a di semua level$.a[0]→ elemen index 0$.a[0:3]→ slice elemen 0 sampai 2$.a[-1]→ elemen terakhir$.a[?(@.x>10)]→ filter berdasarkan kondisi$.a[0,2]→ union index 0 dan 2$.a.*→ sama seperti$.a[*]untuk object
Di Mana JSONPath Biasa Dipakai?
Beberapa skenario nyata di mana JSONPath sangat membantu:
- Testing API — di Postman atau REST Assured, JSONPath dipakai untuk assert nilai tertentu dari response tanpa parsing manual seluruh body.
- Log processing — tools seperti Logstash atau Fluentd memakai JSONPath untuk mengekstrak field spesifik dari log JSON sebelum dikirim ke sistem monitoring.
- Konfigurasi dinamis — beberapa API gateway (misalnya Kong atau AWS API Gateway mapping template) menggunakan JSONPath untuk transformasi request/response.
- Data pipeline — mengambil subset data dari payload besar sebelum diproses lebih lanjut, tanpa perlu load seluruh struktur ke memory dalam bentuk object.
Perbedaan Antar Implementasi
Perlu dicatat: JSONPath tidak punya spesifikasi resmi tunggal yang universal seperti JSON Schema (walau ada usulan RFC 9535 yang mulai distandarkan). Artinya, sintaks filter expression, dukungan negative index, atau fungsi tambahan (seperti length()) bisa sedikit berbeda antara library Python, JavaScript, Java, atau Go. Selalu cek dokumentasi library yang kamu pakai kalau ada perilaku yang tidak sesuai ekspektasi.
Tips praktis lain: kalau kamu baru belajar JSONPath, jangan langsung menulis query rumit dengan banyak filter sekaligus. Mulai dari path sederhana dulu (misalnya $.store.books), pastikan hasilnya benar, lalu tambahkan wildcard atau filter satu per satu. Cara ini jauh lebih mudah untuk debugging dibanding menulis satu ekspresi panjang lalu bingung kenapa hasilnya kosong. Banyak online tester JSONPath juga menampilkan hasil secara real-time, jadi kamu bisa langsung lihat efek setiap perubahan sintaks tanpa harus menjalankan kode di editor terpisah.
JSONPath Cheatsheet: How to Query and Filter Nested JSON Data
If you've ever worked with an API response that's JSON nested many levels deep — arrays inside objects, objects inside arrays, five or six levels down — you've probably gotten tired of scrolling manually just to find one field. That's where JSONPath comes in. JSONPath is a dedicated query language for JSON, similar to XPath for XML, that lets you extract or filter data from complex JSON structures using a single expression.
This article is a practical cheatsheet: the most commonly used JSONPath syntax, complete with sample data and query results, so you can copy, paste, and adapt it to your own needs right away.
What is JSONPath?
JSONPath was first popularized by Stefan Gössner in 2007 as a way to navigate JSON documents declaratively. Today JSONPath is used across many tools — from programming libraries (Python's jsonpath-ng, JavaScript's jsonpath-plus) to API gateways and observability tools like Grafana and Postman, which offer "extract variable from response" features built on JSONPath.
The basic concept: you start from the document root (denoted $), then "descend" into properties or array elements using dot notation or bracket notation — similar to how you'd access an object in JavaScript.
Sample Data Used in This Cheatsheet
For consistency, every example below uses the following JSON data — a bookstore with a list of books and store info:
{
"store": {
"name": "Nusantara Bookstore",
"location": "Jakarta",
"books": [
{ "title": "Laskar Pelangi", "author": "Andrea Hirata", "price": 55000, "category": "fiction", "stock": 12 },
{ "title": "Bumi Manusia", "author": "Pramoedya Ananta Toer", "price": 68000, "category": "fiction", "stock": 0 },
{ "title": "Filosofi Teras", "author": "Henry Manampiring", "price": 89000, "category": "nonfiction", "stock": 30 },
{ "title": "Sapiens", "author": "Yuval Noah Harari", "price": 120000, "category": "nonfiction", "stock": 5 }
]
}
}
JSONPath Basic Syntax
$— the root of the JSON document.— child operator, accesses a property directly[]— bracket notation, an alternative to dot notation, required when a property name has spaces or special characters*— wildcard, meaning "all elements" at that level..— recursive descent, searches every level regardless of depth[n]— accesses the array element at index n (zero-based)[start:end]— array slice, grabs a range of elements[?(expression)]— filter expression, returns elements matching a condition[,]— union, selects multiple indices or names at once
Basic Query Examples
Get the store name (root → child → child):
$.store.name
// result: "Nusantara Bookstore"
Get every book title using a wildcard:
$.store.books[*].title
// result: ["Laskar Pelangi", "Bumi Manusia", "Filosofi Teras", "Sapiens"]
Get the first book in the array (index starts at 0):
$.store.books[0]
// result: { "title": "Laskar Pelangi", "author": "Andrea Hirata", ... }
Get the first two books using an array slice:
$.store.books[0:2]
// result: [Laskar Pelangi, Bumi Manusia]
Get the last book using a negative index (supported by most implementations):
$.store.books[-1:]
// result: [Sapiens]
Recursive Descent: Search Every Level
The .. operator is extremely handy when you don't know exactly what level a field sits at, or when that field appears repeatedly at different depths. For example, getting every price value regardless of position:
$..price
// result: [55000, 68000, 89000, 120000]
This is equivalent to "find a field named price, anywhere, at any depth" — extremely useful for API payloads whose structure isn't consistent across versions.
Filter Expressions: Query With Conditions
The most powerful part of JSONPath is the filter expression [?(...)], which lets you filter an array based on a condition — similar to a WHERE clause in SQL.
Get every book priced above 60000:
$.store.books[?(@.price > 60000)]
// result: Bumi Manusia, Filosofi Teras, Sapiens
The @ symbol here refers to the current node being evaluated, as opposed to $, which always refers to the root.
Get out-of-stock fiction books:
$.store.books[?(@.category == 'fiction' && @.stock == 0)]
// result: Bumi Manusia
Get only the titles of books priced under 90000:
$.store.books[?(@.price < 90000)].title
// result: ["Laskar Pelangi", "Bumi Manusia", "Filosofi Teras"]
Union: Select Several at Once
If you only need specific indices or property names, use a comma as a union operator:
$.store.books[0,2].title
// result: ["Laskar Pelangi", "Filosofi Teras"]
Quick Reference Table
$→ document root$.a.b→ chained child properties$.a[*]→ every element in array a$..a→ find property a at every level$.a[0]→ element at index 0$.a[0:3]→ slice elements 0 through 2$.a[-1]→ last element$.a[?(@.x>10)]→ conditional filter$.a[0,2]→ union of index 0 and 2$.a.*→ same as$.a[*]for an object
Where Is JSONPath Actually Used?
A few real-world scenarios where JSONPath shines:
- API testing — in Postman or REST Assured, JSONPath is used to assert specific response values without manually parsing the entire body.
- Log processing — tools like Logstash or Fluentd use JSONPath to extract specific fields from JSON logs before shipping them to monitoring systems.
- Dynamic configuration — some API gateways (e.g. Kong or AWS API Gateway mapping templates) use JSONPath for request/response transformation.
- Data pipelines — pulling a subset of data from a large payload before further processing, without loading the entire structure into memory as an object.
Differences Between Implementations
Worth noting: JSONPath doesn't have a single universal official spec the way JSON Schema does (though there's an RFC 9535 proposal now being standardized). That means filter expression syntax, negative index support, or extra functions (like length()) can vary slightly between Python, JavaScript, Java, or Go libraries. Always check the docs of the specific library you're using if something doesn't behave as expected.