JSON Path Syntax: Complete Guide with Examples

May 26, 202610 min read

What is JSON Path?

JSON Path is a query language for JSON, similar to how XPath is used for XML. It allows you to extract specific data from JSON documents using a concise, expressive syntax. Whether you're working with APIs, configuration files, or complex data structures, JSON Path helps you navigate and filter JSON data efficiently.

Originally proposed by Stefan Goessner in 2007, JSON Path has become a standard tool in many programming ecosystems. Libraries exist for JavaScript, Python, Java, PHP, and many other languages.

Basic Syntax and Operators

The Root Element: $

Every JSON Path expression starts with $, which represents the root of the JSON document.

{
  "store": {
    "name": "Book Store",
    "books": [
      {"title": "Book A", "price": 10},
      {"title": "Book B", "price": 20}
    ]
  }
}
// JSON Path expression
$.store.name  // Returns: "Book Store"

// JavaScript equivalent using lodash
_.get(data, 'store.name');

Current Node: @

The @ symbol refers to the current node being processed, especially useful inside filters.

// Find books with price greater than 15
$.store.books[?(@.price > 15)]

// The @ refers to each book object during iteration

Wildcard: *

The asterisk matches all elements at the current level.

// Get all properties of the store object
$.store.*

// Get all book titles
$.store.books[*].title

Dot Notation vs Bracket Notation

JSON Path supports two styles for accessing properties:

Dot Notation (cleaner, preferred when keys are simple):

$.store.name
$.store.books[0].title

Bracket Notation (required for special characters or dynamic keys):

$['store']['name']
$['store']['books'][0]['title']

// Useful when key contains spaces or special characters
$['user settings']['theme color']

Array Access and Slicing

Index Access

// First book
$.store.books[0]

// Last book (using -1 is not standard, but some implementations support it)
// Standard approach: use length - 1 in your code

Array Slices

The slice syntax [start:end:step] allows you to extract ranges from arrays.

// First two books
$.store.books[0:2]

// Every other book starting from index 0
$.store.books[0:4:2]

// From index 1 to end
$.store.books[1:]

Slice Parameters:

ParameterDescriptionDefault
startStarting index (inclusive)0
endEnding index (exclusive)Array length
stepStep size1

Filters: The Powerful ?() Syntax

Filters allow you to select items based on conditions. This is where JSON Path becomes truly powerful.

Basic Comparisons

// Books cheaper than 15
$.store.books[?(@.price < 15)]

// Books with a specific title
$.store.books[?(@.title == 'Book A')]

Logical Operators

// Books that are cheap AND fiction
$.store.books[?(@.price < 15 && @.category == 'fiction')]

// Books that are either cheap OR on sale
$.store.books[?(@.price < 10 || @.onsale == true)]

Supported Operators

OperatorDescriptionExample
==Equal?(@.price == 10)
!=Not equal?(@.type != 'ebook')
<Less than?(@.price < 20)
<=Less or equal?(@.rating <= 4.5)
>Greater than?(@.price > 10)
>=Greater or equal?(@.pages >= 300)
=~Regex match?(@.title =~ /book/i)
inIn array?(@.category in ['fiction','drama'])
ninNot in array?(@.status nin ['outdated','deleted'])

Existential Checks

// Books that have an 'isbn' field
$.store.books[?(@.isbn)]

// Books that DON'T have a 'discount' field
$.store.books[?!@.discount]

Recursive Descent: ..

The double dot operator searches for matching nodes at any depth in the tree.

// Find all price values anywhere in the document
$.store..price

// Find all objects that have a 'title' field
$..title

Warning: Recursive descent can be expensive on large documents. Use it judiciously.

JSON Path vs XPath: A Comparison

FeatureJSON PathXPath
Data FormatJSONXML
Root$/
Current Node@.
Wildcard**
Filter?()[] with predicates
Recursive..//
Array Index[0][1] (XPath is 1-indexed)
Attribute Access.name@name

Example Comparison

JSON Path:

$.store.books[?(@.price < 15)].title

XPath equivalent:

/store/books[price < 15]/title

Practical Examples

Example 1: API Response Parsing

{
  "data": {
    "users": [
      {"id": 1, "name": "Alice", "active": true, "role": "admin"},
      {"id": 2, "name": "Bob", "active": false, "role": "user"},
      {"id": 3, "name": "Charlie", "active": true, "role": "user"}
    ],
    "total": 3
  }
}
// Get all active user names
$.data.users[?(@.active == true)].name
// Result: ["Alice", "Charlie"]

// Get admin user IDs
$.data.users[?(@.role == 'admin')].id
// Result: [1]

Example 2: Configuration Extraction

{
  "environments": {
    "dev": {"api_url": "dev.api.com", "debug": true},
    "prod": {"api_url": "api.com", "debug": false}
  }
}
// Get all API URLs
$.environments.*.api_url
// Result: ["dev.api.com", "api.com"]

// Check if any environment has debug enabled
$.environments[?(@.debug == true)]

Common Pitfalls and Tips

  1. Indexing starts at 0 (unlike XPath which starts at 1)
  2. String comparisons are case-sensitive unless you use regex with i flag
  3. Not all implementations support all features — check your library's documentation
  4. Use .. sparingly on large documents as it traverses the entire tree
  5. Filters can only be used on arrays, not objects

Testing JSON Path Expressions

You can test JSON Path expressions using:

  • Online evaluators like jsonpath.com
  • Browser console with libraries like jsonpath-plus
  • Node.js with jsonpath or jsonpath-plus packages
npm install jsonpath-plus
import { JSONPath } from 'jsonpath-plus';

const result = JSONPath({ path: '$.store.books[*].title', json: data });
console.log(result); // ['Book A', 'Book B']