JSONPath QUERY Request Body Support
Categories: Change Log, API Testing, HTTP Methods
API Challenges now supports JSONPath expressions in QUERY request bodies.
This means our API QUERY endpoints advertise and accept:
Content-Type: application/jsonpath
The original QUERY support used form-encoded content:
Content-Type: application/x-www-form-urlencoded`
The payload would use normal form encoding like:
type=book
Form-encoded content still works. JSONPath adds another way to describe read-only selection criteria in the body of a QUERY request.
One of the key advantages for QUERY is the support for multiple content types supporting different query styles and filtering representations. And when the API is properly written, the API itself will use the accept-query header to tell the client what formats are supported:
accept-query: application/x-www-form-urlencoded, application/jsonpath
What is JSONPath?
JSONPath is a query syntax for JSON documents. It lets us select values from a JSON structure in a similar spirit to how XPath selects values from XML.
The standard is RFC 9535, published in February 2024. The RFC defines JSONPath as a syntax for selecting and extracting JSON values from a JSON value.
A JSONPath expression usually starts with $, which means the root of the JSON document.
For a response like this:
{
"items": [
{
"id": 1,
"type": "book",
"price": 9.99,
"numberinstock": 3,
"isbn13": "123-4-56-789012-3"
}
]
}
The expression:
$.items[?(@.type == 'book')]
selects every item where the type field is book.
Why Use JSONPath?
JSONPath is useful when the query is more structured than a simple field/value filter.
A URL query string works well for simple examples:
/simpleapi/items?type=book
But a request body can be easier to read when the query has multiple conditions or when you want a syntax that already describes JSON data.
For example:
$.items[?(@.type == 'book' && @.numberinstock > 0)]
That expression reads as "from the items collection, return books where the number in stock is greater than zero."
Examples Using Simple API
The Simple API has an /simpleapi/items collection with fields such as type, price, numberinstock, and isbn13.
To return only books:
QUERY /simpleapi/items HTTP/1.1
Content-Type: application/jsonpath
Accept: application/json
$.items[?(@.type == 'book')]
To return CDs:
$.items[?(@.type == 'cd')]
To return out-of-stock items:
$.items[?(@.numberinstock == 0)]
To return books that have stock:
$.items[?(@.type == 'book' && @.numberinstock > 0)]
To return all items:
$.items
For API Challenges todos, the equivalent completed-todo query is:
QUERY /todos HTTP/1.1
Content-Type: application/jsonpath
Accept: application/json
$.todos[?(@.doneStatus == true)]
Why Use JSONPath With QUERY?
QUERY is intended for safe read requests where the query content belongs in the request body rather than the URL.
JSONPath pairs well with QUERY because:
- the HTTP method still communicates "this is a read";
- the URL can stay focused on the collection resource;
- the request body can contain a structured query expression;
- the
Content-Typeheader documents the query language; - clients can discover support through the
Accept-Queryresponse header.
This gives testers another useful behavior to explore. Does your REST client support custom methods? Does it allow a request body with QUERY? Does it preserve Content-Type: application/jsonpath? Does generated OpenAPI documentation show the content type clearly?
Try the New Challenge
There is now an API Challenge for JSONPath query bodies:
And the reference material has been expanded:
Try the Simple API examples first, then use the challenge to prove that your request is doing what you think it is doing.