Quick Tips
3 min
JSONPath for API Testing
Extract and validate data from JSON responses using JSONPath
...
jsonjsonpathapi-testing
JSONPath for API Testing
Sample JSON Response
{
"status": "success",
"data": {
"user": {
"id": 12345,
"name": "John Doe",
"email": "john@example.com",
"roles": ["admin", "user"],
"settings": {
"notifications": true,
"theme": "dark"
}
},
"orders": [
{
"id": "ORD-001",
"total": 99.99,
"status": "completed",
"items": [
{"name": "Product A", "price": 49.99},
{"name": "Product B", "price": 50.00}
]
},
{
"id": "ORD-002",
"total": 149.99,
"status": "pending",
"items": [
{"name": "Product C", "price": 149.99}
]
}
]
}
}1. Basic JSONPath Syntax
// Root element
$
// Direct child
$.status // "success"
$.data.user.name // "John Doe"
// Array access by index
$.data.orders[0] // First order
$.data.orders[0].id // "ORD-001"
$.data.orders[-1] // Last order
// All elements in array
$.data.orders[*] // All orders
$.data.orders[*].status // All order statuses2. Array and Filter Operations
// Array slice
$.data.orders[0:2] // First 2 orders
$.data.orders[1:] // All except first
$.data.orders[-2:] // Last 2 orders
// Filter by value
$.data.orders[?(@.status == 'completed')]
$.data.orders[?(@.total > 100)]
$.data.orders[?(@.status != 'cancelled')]
// Multiple conditions
$.data.orders[?(@.status == 'completed' && @.total > 50)]
$.data.orders[?(@.status == 'pending' || @.status == 'processing')]
// Filter and extract
$.data.orders[?(@.status == 'completed')].id
// Result: ["ORD-001"]3. Using in REST Assured (Java)
import io.restassured.RestAssured;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
public class APITest {
@Test
public void testJSONPath() {
given()
.baseUri("https://api.example.com")
.when()
.get("/user/12345")
.then()
.statusCode(200)
// Extract values
.body("status", equalTo("success"))
.body("data.user.name", equalTo("John Doe"))
.body("data.user.email", containsString("@example.com"))
// Array size
.body("data.orders.size()", equalTo(2))
.body("data.user.roles.size()", greaterThan(0))
// Array contains
.body("data.user.roles", hasItem("admin"))
.body("data.orders.id", hasItems("ORD-001", "ORD-002"))
// Filter and validate
.body("data.orders.findAll { it.status == 'completed' }.size()",
equalTo(1))
.body("data.orders.find { it.total > 100 }.id",
equalTo("ORD-002"));
}
@Test
public void extractAndUseValue() {
// Extract value for later use
String userId =
given()
.baseUri("https://api.example.com")
.when()
.post("/users")
.then()
.statusCode(201)
.extract()
.path("data.user.id");
// Use extracted value
given()
.baseUri("https://api.example.com")
.pathParam("id", userId)
.when()
.get("/users/{id}")
.then()
.statusCode(200);
}
}4. Using in Postman
// Tests tab in Postman
pm.test("Status is success", function() {
var jsonData = pm.response.json();
pm.expect(jsonData.status).to.eql("success");
});
pm.test("User name is correct", function() {
var jsonData = pm.response.json();
pm.expect(jsonData.data.user.name).to.eql("John Doe");
});
pm.test("Has admin role", function() {
var jsonData = pm.response.json();
pm.expect(jsonData.data.user.roles).to.include("admin");
});
pm.test("First order is completed", function() {
var orders = pm.response.json().data.orders;
pm.expect(orders[0].status).to.eql("completed");
});
// Using JSONPath (requires jsonpath library)
pm.test("All completed orders", function() {
var jsonData = pm.response.json();
var completed = jsonpath.query(jsonData,
"$.data.orders[?(@.status=='completed')]");
pm.expect(completed.length).to.be.above(0);
});
// Save to environment variable
var token = pm.response.json().data.user.token;
pm.environment.set("auth_token", token);5. Using in Python (requests + jsonpath-ng)
import requests
from jsonpath_ng import parse
response = requests.get("https://api.example.com/user/12345")
data = response.json()
# Basic extraction
status = parse('$.status').find(data)[0].value
print(f"Status: {status}")
# Nested value
user_name = parse('$.data.user.name').find(data)[0].value
print(f"Name: {user_name}")
# Array values
order_ids = [match.value for match in
parse('$.data.orders[*].id').find(data)]
print(f"Order IDs: {order_ids}")
# Filter (using jsonpath-ng.ext)
from jsonpath_ng.ext import parse as parse_ext
completed_orders = parse_ext(
'$.data.orders[?(@.status=="completed")]'
).find(data)
for order in completed_orders:
print(f"Completed Order: {order.value['id']}")6. Common API Testing Patterns
Validate Response Structure:
.then()
.body("status", notNullValue())
.body("data", notNullValue())
.body("data.user", hasKey("id"))
.body("data.user", hasKey("email"))
.body("data.orders", instanceOf(List.class));Validate All Array Elements:
// All orders have required fields
.body("data.orders.id", everyItem(notNullValue()))
.body("data.orders.total", everyItem(greaterThan(0.0)))
.body("data.orders.status",
everyItem(isIn(Arrays.asList("pending", "completed", "cancelled"))));Extract and Compare:
// Extract multiple values
List<String> orderIds =
response.jsonPath().getList("data.orders.id");
List<Double> totals =
response.jsonPath().getList("data.orders.total", Double.class);
// Validate
Assert.assertTrue(orderIds.size() > 0);
Assert.assertTrue(totals.stream().allMatch(t -> t > 0));Deep Nested Extraction:
// Get all product names from all orders
List<String> productNames =
response.jsonPath().getList("data.orders.items.flatten().name");
// Sum of all prices
List<Double> allPrices =
response.jsonPath().getList("data.orders.items.flatten().price");
double total = allPrices.stream().mapToDouble(Double::doubleValue).sum();7. Advanced Filters
// Regex match
$.data.orders[?(@.id =~ /ORD-.*/)]
// Contains
$.data.orders[?(@.status in ['pending', 'processing'])]
// Exists
$.data.orders[?(@.trackingNumber)]
// Multiple conditions with complex logic
$.data.orders[?(
@.status == 'completed' &&
@.total > 50 &&
@.items.length > 1
)]
// Nested filter
$.data.orders[?(@.items[?(@.price > 100)])]8. JSONPath in JMeter
JSON Path Extractor:
Names of created variables: orderId
JSON Path expressions: $.data.orders[0].id
Match No: 1
Default Values: NOT_FOUND
JSON Assertion:
Assert JSON Path exists: $.status
Additionally assert value: true
Expected Value: successQuick Reference
Common JSONPath Expressions
| Expression | Description | Example Result |
|---|---|---|
$ | Root | Entire object |
$.field | Direct child | Field value |
$..field | Recursive descent | All field occurrences |
$[0] | Array index | First element |
$[-1] | Last element | Last element |
$[*] | All elements | All array items |
$[0:2] | Array slice | First 2 elements |
$[?(@.field)] | Filter exists | Items with field |
$[?(@.x > 5)] | Filter value | Items where x > 5 |
Operators in Filters
| Operator | Description |
|---|---|
== | Equal |
!= | Not equal |
<, >, <=, >= | Comparison |
&& | AND |
| ` | |
=~ | Regex match |
in | In array |
Key Takeaways
- Use
$to start from root of JSON - Use
.for nested field access - Use
[*]to get all array elements - Use
[?(@.field)]to filter arrays - Combine filters with
&&and|| - Extract values for use in subsequent requests
- Validate array sizes and element properties
- Test for field existence with
hasKey()or filters
Comments (0)
Loading comments...