JSONPath Tester Guide: Query JSON Data with Expressions

By Suvom Das March 12, 2026 15 min read

1. What Is JSONPath?

JSONPath is a query language for extracting data from JSON documents, analogous to how XPath queries XML. Originally proposed by Stefan Goessner in 2007, JSONPath has become a widely used standard for navigating and selecting elements within JSON structures.

In an era where JSON is the dominant data interchange format for APIs, configuration files, and data storage, the ability to precisely query JSON data is essential. JSONPath provides a concise, expressive syntax for selecting specific values, filtering arrays, and navigating deeply nested structures without writing custom parsing code.

JSONPath is supported in a wide ecosystem of tools and languages: JavaScript (jsonpath, jsonpath-plus), Python (jsonpath-ng, jsonpath-rw), Java (Jayway JsonPath), PHP (JsonPath), Kubernetes (kubectl), Postman, and many API testing frameworks. In 2023, JSONPath was formalized as RFC 9535, providing an official standard after years of implementation-specific variations.

A simple example: given a JSON document containing user data, the JSONPath expression $.users[0].name extracts the name of the first user. More complex expressions can filter arrays by conditions, search recursively through nested structures, and select multiple paths simultaneously.

2. JSONPath Syntax Overview

JSONPath expressions always start with $, which represents the root of the JSON document. From there, you build paths using operators that navigate the structure.

Core Operators

Operator        Description                          Example
$               Root object/element                  $
.property       Child property (dot notation)        $.store
['property']    Child property (bracket notation)     $['store']
[n]             Array element by index               $[0]
[start:end]     Array slice                          $[0:3]
*               Wildcard (all children)              $.store.*
..              Recursive descent                    $..author
[?()]           Filter expression                    $[?(@.price<10)]
[,]             Union (multiple indices/names)       $[0,2,4]

Sample JSON Document

Most JSONPath examples use a variation of the classic "bookstore" document. We will use this throughout the guide:

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

3. Dot Notation and Bracket Notation

JSONPath offers two ways to access child properties: dot notation and bracket notation. Both achieve the same result for simple property names.

Dot Notation

Dot notation is concise and familiar to JavaScript developers:

$.store.book            -- the book array
$.store.bicycle.color   -- "red"
$.store.book[0].author  -- "Nigel Rees"
$.store.book[0].title   -- "Sayings of the Century"

Bracket Notation

Bracket notation uses quoted property names inside square brackets:

$['store']['book']              -- the book array
$['store']['bicycle']['color']  -- "red"
$['store']['book'][0]['author'] -- "Nigel Rees"

When to Use Bracket Notation

Bracket notation is required when property names contain special characters, spaces, hyphens, or start with digits:

// Properties with special characters
$['first-name']              -- hyphenated property
$['my property']             -- property with space
$['123']                     -- property starting with digit
$['@type']                   -- property with @ symbol

// Dot notation would FAIL for these:
$.first-name                 -- interpreted as $.first minus name
$.my property                -- syntax error
$.123                        -- ambiguous (number or property?)

4. Wildcards and Union

Wildcard (*)

The wildcard operator * matches all children of the current element. It works on both objects (all property values) and arrays (all elements).

$.store.*               -- all things in the store (book array + bicycle object)
$.store.book[*]         -- all books
$.store.book[*].author  -- all authors: ["Nigel Rees", "Evelyn Waugh",
                           "Herman Melville", "J. R. R. Tolkien"]
$.*                     -- all top-level values

Union Operator ([,])

The union operator selects multiple specific indices or property names in a single expression:

// Multiple array indices
$.store.book[0,2]          -- first and third books

// Multiple properties (some implementations)
$.store.book[0]['title','author']  -- title and author of first book

// Multiple indices with different spacing
$.store.book[0, 1, 3]     -- first, second, and fourth books

5. Recursive Descent

The recursive descent operator (..) is one of JSONPath's most powerful features. It searches the entire document tree for matching property names, regardless of depth.

$..author     -- ALL author values anywhere in the document
              -- ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien"]

$..price      -- ALL price values (books + bicycle)
              -- [8.95, 12.99, 8.99, 22.99, 399.99]

$..isbn       -- ALL isbn values (only books that have isbn)
              -- ["0-553-21311-3", "0-395-19395-8"]

$..book[0]    -- first book (found via recursive search for "book")

$..*          -- ALL values at ALL levels (entire document flattened)

Recursive descent is particularly useful when:

Performance Consideration

Recursive descent searches the entire document tree, which can be expensive for large JSON documents. Use specific paths when you know the structure, and reserve recursive descent for exploration or cases where the path is genuinely variable.

6. Array Indexing and Slicing

JSONPath supports flexible array access through indexing and slicing, similar to Python's list slicing.

Index Access

$.store.book[0]    -- first book (index 0)
$.store.book[1]    -- second book (index 1)
$.store.book[-1]   -- last book (negative indexing)
$.store.book[-2]   -- second-to-last book

Array Slicing [start:end:step]

Slicing uses the syntax [start:end:step], where start is inclusive, end is exclusive, and step is the increment. All three are optional.

$.store.book[0:2]    -- first two books (index 0 and 1)
$.store.book[1:3]    -- second and third books
$.store.book[:2]     -- first two books (start defaults to 0)
$.store.book[2:]     -- from third book to end
$.store.book[-2:]    -- last two books
$.store.book[::2]    -- every other book (step of 2)
$.store.book[::-1]   -- all books in reverse order

Slicing Examples

Given array: ["a", "b", "c", "d", "e"]

$[0:3]    -- ["a", "b", "c"]         (indices 0, 1, 2)
$[1:4]    -- ["b", "c", "d"]         (indices 1, 2, 3)
$[:2]     -- ["a", "b"]              (first 2)
$[3:]     -- ["d", "e"]              (from index 3 to end)
$[-2:]    -- ["d", "e"]              (last 2)
$[0:5:2]  -- ["a", "c", "e"]         (every other, starting at 0)
$[1:5:2]  -- ["b", "d"]              (every other, starting at 1)

7. Filter Expressions

Filter expressions allow you to select array elements or object properties based on conditions. They use the syntax [?(@.property operator value)], where @ refers to the current element being evaluated.

Comparison Operators

==    Equal to
!=    Not equal to
<     Less than
<=    Less than or equal to
>     Greater than
>=    Greater than or equal to

Filter Examples

// Books cheaper than 10
$.store.book[?(@.price < 10)]
// Returns books by Nigel Rees (8.95) and Herman Melville (8.99)

// Fiction books only
$.store.book[?(@.category == 'fiction')]
// Returns books by Evelyn Waugh, Herman Melville, J. R. R. Tolkien

// Books with ISBN
$.store.book[?(@.isbn)]
// Returns books that have an isbn property (Moby Dick, Lord of the Rings)

// Books by a specific author
$.store.book[?(@.author == 'Herman Melville')]
// Returns the Moby Dick book object

// Expensive books (price >= 20)
$.store.book[?(@.price >= 20)]
// Returns The Lord of the Rings (22.99)

// Books NOT in the fiction category
$.store.book[?(@.category != 'fiction')]
// Returns Sayings of the Century (reference)

Combining Filters

Some implementations support logical operators within filters:

// Books that are fiction AND cost less than 15
$.store.book[?(@.category == 'fiction' && @.price < 15)]

// Books that are reference OR cost more than 20
$.store.book[?(@.category == 'reference' || @.price > 20)]

// Negation
$.store.book[?(!@.isbn)]
// Books without an isbn property

Note that logical operator support varies between implementations. RFC 9535 standardizes && (logical AND), || (logical OR), and ! (logical NOT) for filter expressions.

Existence Check

// Check if a property exists
$.store.book[?(@.isbn)]      -- books that have an isbn property
$.store.book[?(@.discount)]  -- books that have a discount property

// This works because @.isbn evaluates to a truthy value if the
// property exists and has a value, or falsy if it does not exist.

8. Practical Query Examples

Here are practical JSONPath examples for common real-world JSON structures.

API Response Parsing

// GitHub API response
{
  "items": [
    {
      "full_name": "facebook/react",
      "stargazers_count": 220000,
      "language": "JavaScript",
      "topics": ["javascript", "frontend", "ui"]
    },
    ...
  ]
}

// All repository names
$.items[*].full_name

// Repos with 100k+ stars
$.items[?(@.stargazers_count > 100000)].full_name

// All topics from all repos
$.items[*].topics[*]

Kubernetes Resource Queries

// kubectl uses JSONPath extensively
# Get all pod names
kubectl get pods -o jsonpath='{.items[*].metadata.name}'

# Get all container images
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}'

# Get pod name and status
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'

# Get nodes with their addresses
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'

Configuration File Queries

// Package.json
{
  "name": "my-app",
  "dependencies": {
    "react": "^18.2.0",
    "axios": "^1.6.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test"
  }
}

// All dependency names (keys)
// Note: JSONPath key extraction varies by implementation

// Get specific script
$.scripts.build    -- "react-scripts build"

// Check if a dependency exists
$.dependencies.react  -- "^18.2.0"

Nested Data Extraction

// E-commerce order
{
  "order": {
    "id": "ORD-001",
    "customer": {
      "name": "Alice",
      "address": {
        "city": "New York",
        "state": "NY"
      }
    },
    "items": [
      {"product": "Widget", "qty": 2, "price": 9.99},
      {"product": "Gadget", "qty": 1, "price": 24.99}
    ]
  }
}

// Customer city
$.order.customer.address.city     -- "New York"

// All product names
$.order.items[*].product          -- ["Widget", "Gadget"]

// Items costing more than 10
$.order.items[?(@.price > 10)]    -- [{"product":"Gadget",...}]

// Total item count (need to process result)
$.order.items.length()            -- 2 (implementation-dependent)

9. JSONPath vs. Alternatives

Several tools and languages exist for querying JSON data. Understanding the differences helps you choose the right tool for each situation.

JSONPath vs. jq

Feature          JSONPath              jq
Purpose          Query/extract         Query + transform + construct
Syntax           $.store.book[0]       .store.book[0]
Filtering        [?(@.price<10)]       select(.price < 10)
Transformation   Limited               Full (map, reduce, group_by)
Conditionals     Filter only           if-then-else
Functions        Minimal               Rich built-in library
Standalone tool  No (library)          Yes (CLI tool)
Embedded use     APIs, libraries       CLI, scripts
Learning curve   Low                   Medium-High

Use JSONPath when you need simple data extraction within an application or API. Use jq when you need complex transformation, data reshaping, or command-line JSON processing.

JSONPath vs. XPath

JSONPath              XPath                 Purpose
$                     /                     Root
$.store               /store                Child
$..author             //author              Recursive descent
$.store.book[0]       /store/book[1]        Array index (0 vs 1 based)
$.store.book[*]       /store/book           All elements
[?(@.price<10)]       [price<10]            Filter
@                     .                     Current node

JSONPath was designed as a JSON analog of XPath, with syntax adapted for JSON's structure. The most notable difference is that JSONPath uses zero-based array indexing while XPath uses one-based.

JSONPath vs. JSON Pointer (RFC 6901)

JSONPath             JSON Pointer         Notes
$.store.book[0]      /store/book/0        Pointer uses / separator
$.store.bicycle      /store/bicycle       Simpler syntax in Pointer
$..author            (not supported)      No recursive descent
[?(@.price<10)]      (not supported)      No filtering
$.store.*            (not supported)      No wildcards

JSON Pointer is a simpler, more limited specification designed for addressing a single value within a JSON document. It is used in JSON Patch (RFC 6902) and JSON Schema references. JSONPath is more expressive but more complex.

10. Using Our Free JSONPath Tester Tool

Our JSONPath Tester lets you paste any JSON document and test JSONPath expressions interactively. See results instantly as you type your expression, with syntax highlighting for both the JSON input and the matched results.

The tool supports all standard JSONPath operators including dot notation, bracket notation, recursive descent, array slicing, wildcards, unions, and filter expressions. It highlights matched elements in the source JSON, provides expression auto-completion hints, and includes a library of example expressions to help you learn the syntax.

Whether you are building API integrations, writing Kubernetes JSONPath queries, extracting data from complex JSON responses, or learning JSONPath syntax, this tester provides instant feedback and makes experimentation easy.

Try the JSONPath Tester

Frequently Asked Questions

What is JSONPath?

JSONPath is a query language for JSON data, analogous to XPath for XML. It uses expressions starting with $ (root) to navigate and extract values from JSON structures. It supports dot/bracket notation, wildcards, recursive descent, filtering, and array slicing.

What is the difference between dot notation and bracket notation?

Dot notation ($.store.book) is concise for simple property names. Bracket notation ($['store']['book']) handles special characters, spaces, and reserved words in property names. Both produce the same result for standard names.

How does recursive descent (..) work?

The .. operator searches the entire JSON tree for a property name at any depth. $..author finds all "author" values regardless of where they appear in the hierarchy.

How do you filter arrays in JSONPath?

Use filter expressions: [?(@.property operator value)]. The @ symbol refers to the current element. Example: $.store.book[?(@.price < 10)] returns all books priced under 10.

What is array slicing in JSONPath?

Array slicing uses [start:end:step] to select ranges. $[0:3] selects the first three elements, $[-2:] selects the last two, and $[::2] selects every other element.

How is JSONPath different from jq?

JSONPath is a query language for extracting data, while jq is a full JSON processor with transformation, construction, and programming features. JSONPath is simpler and embedded in libraries/APIs; jq is more powerful as a standalone CLI tool.