JSONPath array slice

$.store.book[0:2]

$.store.book[0:2] selects the first two books, at indexes 0 and 1. A slice is [start:end:step] (RFC 9535 section 2.3.4): start is included, end is not, step defaults to 1, and any of the three can be left out. A negative bound counts from the end of the array, as in Python.

Slices on the bookstore

The RFC’s bookstore, in the tester below, has four books. With .title added to each query:

[0:2]      Sayings of the Century, Sword of Honour
[:2]       Sayings of the Century, Sword of Honour
[1:]       Sword of Honour, Moby Dick, The Lord of the Rings
[-2:]      Moby Dick, The Lord of the Rings
[::2]      Sayings of the Century, Moby Dick
[1::2]     Sword of Honour, The Lord of the Rings
[::-1]     The Lord of the Rings, Moby Dick, Sword of Honour, Sayings of the Century
[3:1:-1]   The Lord of the Rings, Moby Dick

Bounds past either end are clamped, so [0:100] selects all four books and never fails. [2:1] selects nothing, and so does a step of 0: RFC 9535 makes [::0] empty where Python raises an error. A slice of an object or a string selects nothing too.

The last element

$.store.book[-1].title is the last book’s title, "The Lord of the Rings", at the normalized path $['store']['book'][3]['title']. [-1:] selects the same node, as a slice.

[(@.length-1)] is how Goessner’s 2007 article wrote it: a script expression, handed to JavaScript to evaluate. RFC 9535 dropped script expressions, and the tester refuses this one and suggests [-1]. Libraries still differ here, in runs of each:

                    [-1]          [-1:]   [(@.length-1)]   [::-1]        [::2]
jsonpath-plus 11.1  nothing       last    last             nothing       works
Jayway 3.0.0        last          last    parse error      parse error   parse error
kubectl 1.32        last          last    parse error      step error    works

Jayway ignores steps: [0:4:2] returns all four books, [3:0:-1] none, and [::2] doesn’t parse. kubectl says step must be > 0, and jsonpath-plus returns every book for [::0]. [-1:] is the one spelling of “last” all of them accept.

Unions

A bracket can hold several selectors: $.store.book[0,1] is the first two books, and $.store.book[0:2,-1].title adds the last, three titles in all. Jayway refuses the second form, and jsonpath-plus drops the -1.

Elsewhere

jq           .store.book[0:2]     .store.book[-1]     (no step)
JMESPath     store.book[0:2]      store.book[-1]      store.book[::-1]
Python       books[0:2]           books[-1]           books[::-1]
JavaScript   books.slice(0, 2)    books.at(-1)        books.toReversed()

Try it in the JSONPath Tester

Member names, wildcards, indexes, slices, descendants and filters, the way RFC 9535 defines them. match() and search() take I-Regexp patterns: . is any character but \n and \r, \p{Lu} is a Unicode category, and there are no \d classes, no backreferences and no anchors.

Selection

2 values selected

PathValue
$['store']['book'][0]{ "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }
$['store']['book'][1]{ "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }

The document, with the selection marked

{
  "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 }
  }
}

Runs in your browser. Nothing you enter is sent anywhere.