JSON Plugin
The plugin provides a set of actions for transformation and validation of JSON data.
Installation
-
Copy the below line to
dependencies
section of the projectbuild.gradle
filePlease make sure to use the same version for all VIVIDUS dependencies. Example 1. build.gradleimplementation(group: 'org.vividus', name: 'vividus-plugin-json', version: '0.6.9')
-
If the project was imported to the IDE before adding new dependency, re-generate the configuration files for the used IDE and then refresh the project in the used IDE.
JSON Path
JSON path expressions always refer to a JSON structure in the same way as XPath expression are used in combination with
an XML document. The "root member object" in JSON path is always referred to as $
regardless if it is an object or array.
JSON path expressions can use the dot–notation
$.store.book[0].title
or the bracket–notation
$['store']['book'][0]['title']
The official JSON path guide conatins examples of JSON paths. Also the number of operators and functions are available for use in JSON paths out of the box. At the same time additional functions provided by this plugin are listed below.
Use JSON path online validator to test your JSON path. |
JSON Path Functions
distinct()
-
distinct()
- removes duplicated items from the input array.
JSON | JSON Path | Result |
---|---|---|
|
|
|
|
|
|
Dynamic variables
JSON context
The variable provides the HTTP response body of the latest executed HTTP call by default or the current JSON element for steps iterating over JSON.
${json-context}
When I execute HTTP GET request for resource with relative URL `/get?productsPerPage=5`
Then number of JSON elements from `${json-context}` by JSON path `$.product` is equal to 5
Table Transformers
FROM_JSON
FROM_JSON
transformer constructs a table by mapping table columns to values found by JSON Paths in the source JSON.
Parameter | Description | ||
---|---|---|---|
|
The name of the variable containing source JSON, only variables of scopes |
||
columns |
The semicolon-separated list of mappings between column names and JSON Paths used to get column values. Example 3. Columns parameter format
|
next_batches
or global
variable registrationDataJson
[
{
"firstName": "Cheryl",
"lastName": "Wilkerson",
"age": 36,
"address": {
"streetAddress": "690 Selah Way",
"city": "Waitsfield",
"postalCode": "05673"
}
},
{
"firstName": "Zachary",
"lastName": "Harrington",
"age": 63,
"address": {
"streetAddress": "4803 Duncan Avenue",
"city": "New York",
"postalCode": "10014"
}
}
]
Given request body: {
"fullName": "<fname> <lname>"
}
When I execute HTTP POST request for resource with URL `https://service-under-test.com/register`
Examples:
{transformer=FROM_JSON, variableName=registrationDataJson, columns=fname=$..firstName;lname=$..lastName}
When I execute HTTP POST request for resource with URL `https://httpbingo.org/anything/path-with-&-ampersand`
Given I initialize scenario variable `jsonData` with value `${json-context}`
When I initialize scenario variable `jsonDataTable` with values:
{transformer=FROM_JSON, variableName=jsonData, columns=host=$..Host}
Then `${jsonDataTable[0].host}` is not equal to `[httpbingo.org]`
Steps
The steps syntax uses two internal (VIVIDUS-only) terms:
-
"JSON element" - any part of JSON document including both complex data structures like
array
,object
and scalar values likestring
in double quotes,number
,boolean
(true
orfalse
) andnull
. -
"JSON element value" or "value of JSON element" - scalar values like
string
not wrapped into double quotes,number
,boolean
(true
orfalse
) andnull
.
Save JSON element value
Saves a value of JSON element found in the given JSON into the variable with the specified name and scope.
When I save JSON element value from `$json` by JSON path `$jsonPath` to $scopes variable `$variableName`
-
$json
- The JSON used to find JSON element value. -
$jsonPath
- The JSON path used to find JSON element value. -
$variableName
- The name of the variable to save the found JSON element value.
When I execute HTTP GET request for resource with URL `https://raw.githubusercontent.com/vividus-framework/JsonPath/master/json-path-web-test/src/main/resources/webapp/json/goessner.json`
When I save JSON element value from `${response}` by JSON path `$.store.book[1].title` to scenario variable `title-of-second-book`
Then `${title-of-second-book}` is equal to `Sword of Honour`
Save JSON element
Saves a JSON element found in the given JSON into the variable with the specified name and scope.
When I save JSON element from `$json` by JSON path `$jsonPath` to $scopes variable `$variableName`
-
json
- The JSON used to find JSON element. -
jsonPath
- The JSON path used to find JSON element value. -
$variableName
- The name of the variable to save the found JSON element.
When I execute HTTP GET request for resource with URL `https://raw.githubusercontent.com/vividus-framework/JsonPath/master/json-path-web-test/src/main/resources/webapp/json/goessner.json`
When I save JSON element from `${response}` by JSON path `$.store.book[1].title` to scenario variable `title-of-second-book`
Then `${title-of-second-book}` is equal to `"Sword of Honour"`
Save number of JSON elements
Saves the number of elements found in the JSON by JSON path into the variable with the specified name and scope.
When I save number of elements from `$json` found by JSON path `$jsonPath` to $scopes variable `$variableName`
-
json
- The JSON used to find JSON elements. -
jsonPath
- The JSON path used to find JSON elements. -
$variableName
- The name of the variable to save the number of elements found in the JSON.
When I save number of elements from `[{"key" : "passed"}, {"key" : "failed"}]` found by JSON path `$..[?(@.key == "failed")]` to scenario variable `messageCount`
Convert JSON to variable
Converts JSON element into the variable with the specified name and scope.
When I convert JSON `$json` to $scopes variable `$variableName`
-
$json
- The JSON used to find JSON element value. -
$variableName
- The name of the variable to save the found JSON element.
When I convert JSON `{
"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
}
],
}
}` to scenario variable `jsonData`
Then `${jsonData.store.book[1].title}` is equal to `Sword of Honour`
Patch JSON
Modified an input JSON using a sequence of operations defined in JSON patch.
When I patch JSON `$sourceJson` using `$jsonPatch` and save result to $scopes variable `$variableName`
-
$sourceJson
- JSON data to be patched. -
$jsonPatch
- JSON data with required patch actions according to RFC-6902 -
$variableName
- The name of the variable to save the patched JSON.
When I patch JSON `{"a":"b"}` using `[{ "op": "replace", "path": "/a", "value": "c" }]` and save result to SCENARIO variable `patchedJson`
Then `{"a":"c"}` is equal to `${patchedJson}`
Execute steps on JSON elements
Executes steps against all elements found by JSON path in the JSON data. The actions performed by the step are:
-
searches for elements using JSON path;
-
checks the elements number matches comparison rule;
-
passes if the comparison rule matches and the elements number is 0;
-
otherwise switches JSON context to each found element and executes all steps (no steps will be executed in case of comparison rule mismatch);
-
restores previous JSON context.
When I find $comparisonRule `$elementsNumber` JSON elements from `$json` by `$jsonPath` and for each element do$stepsToExecute
When I find $comparisonRule '$elementsNumber' JSON elements from '$json' by '$jsonPath' and for each element do$stepsToExecute
-
comparisonRule
- The comparison rule. -
elementsNumber
- The expected number of elements. -
json
- The JSON used to find JSON elements. -
jsonPath
- The JSON path used to find JSON elements. -
stepsToExecute
- The ExamplesTable with a single column containing the steps to execute for each found JSON element.
accountId
consists of digitsWhen I find > `0` JSON elements from `
{
"accounts": [
{
"accountId": 00,
"status": "Active"
},
{
"accountId": 01,
"status": "Active"
},
{
"accountId": 10,
"status": "Active"
}
]
}
` by `$.accounts.*` and for each element do
|step |
|Then number of JSON elements from `${json-context}` by JSON path `$[?(@.accountId =~ /\d+/i)]` is equal to 1 |
Execute steps on JSON elements and exit on condition
Executes steps against all elements found by JSON path in the JSON data until the variable is not set or its value corresponds to the expected one. The actions performed by the step are:
-
searches for elements using JSON path;
-
checks the elements number matches comparison rule;
-
passes if the comparison rule matches and the elements number is 0;
-
otherwise switches JSON context to each found element and executes all steps until the variable is not set or mismatches the expected value (no steps will be executed in case of comparison rule mismatch);
-
restores previous JSON context;
-
fails if the variable has never been set during the iterations execution.
When I find $comparisonRule `$elementsNumber` JSON elements in `$json` by `$jsonPath` and until variable `$variableName` $variableMatcher `$expectedValue` for each element I do:$stepsToExecute
When I find $comparisonRule '$elementsNumber' JSON elements in '$json' by '$jsonPath' and until variable '$variableName' $variableMatcher '$expectedValue' for each element I do:$stepsToExecute
-
comparisonRule
- The comparison rule. -
elementsNumber
- The expected number of elements. -
json
- The JSON used to find JSON elements. -
jsonPath
- The JSON path used to find JSON elements. -
variableName
- The name of the variable to validate. -
variableMatcher
- The string comparison rule. -
expectedValue
- The expected value of the variable. -
stepsToExecute
- The ExamplesTable with a single column containing the steps to execute for each found JSON element.
When I execute HTTP GET request for resource with URL `https://raw.githubusercontent.com/vividus-framework/JsonPath/master/json-path-web-test/src/main/resources/webapp/json/goessner.json`
When I find > `1` JSON elements in `${response}` by `$.store.book` and until variable `title` matches `M.+` for each element I do:
|step|
|When I save JSON element value from `${json-context}` by JSON path `$.title` to scenario variable `title`|
Then `Moby Dick` is = `${title}`
Validate JSON element value
Validates if the given JSON contains the expected JSON element value matching the comparison rule by the specified JSON path.
Then JSON element value from `$json` by JSON path `$jsonPath` $comparisonRule `$expectedValue`
-
$json
- The JSON used to find JSON element value. -
$jsonPath
- The JSON path used to find JSON element value. -
$comparisonRule
- The comparison rule to match JSON element value depending on the element type:-
for
string
- string comparison rules are applicable, -
for
number
- regular comparison rules are applicable, -
for
boolean
- only single ruleIS_EQUAL_TO
(readable form:is equal to
) is allowed, -
for
null
- only two rulesIS_EQUAL_TO
andIS_NOT_EQUAL_TO
(readable forms:is equal to
andis not equal to
) are allowed -
array
andobject
are complex types and must be validated using another steps dedicated for JSON elements.
-
-
$expectedValue
- The expected value of JSON element to match according to the comparison rule.
When I execute HTTP GET request for resource with URL `https://raw.githubusercontent.com/vividus-framework/JsonPath/master/json-path-web-test/src/main/resources/webapp/json/goessner.json`
Then JSON element value from `${response}` by JSON path `$.store.book[3].price` is greater than `22.50`
Validate JSON element
Validates if the given JSON contains the expected JSON element matching the comparison rule by the specified JSON path.
Then JSON element from `$json` by JSON path `$jsonPath` is equal to `$expectedData`$options
-
json
- The JSON used to find the actual JSON element. -
jsonPath
- The JSON path used to find the actual JSON element. -
expectedData
- The expected JSON element to compare against. -
options
- The set of JSON comparison options.
Then JSON element from `
{
"accountId": 12345,
"status": "Active"
}
` by JSON path `$.status` is equal to `"Active"`
Validate number of JSON elements
Validates the number of JSON elements found by the JSON path matches the expected number according to the specified comparison rule.
Then number of JSON elements from `$json` by JSON path `$jsonPath` is $comparisonRule $elementsNumber
-
json
- The JSON used to find the actual JSON elements. -
jsonPath
- The JSON path used to find JSON elements. -
comparisonRule
- The comparison rule. -
elementsNumber
- The expected number of JSON elements.
Then number of JSON elements from `
[
{
"accountId": 843
},
{
"accountId": 233
}
]
` by JSON path `$..accountId` is equal to 2
Validate JSON against schema
Validates JSON against JSON Schema.
Then JSON `$json` is valid against schema `$schema`
-
$json
- The JSON to validate. -
$schema
- The JSON Schema.
The step validates JSON according to schema specification version provided in the schema itself, e.g.:
If the version is not present in the schema then JSON is validated according to 2020-12 version. |
Then JSON `
{
"productId": 1,
"productName": "A desk lamp",
"price": 12.50,
"tags": [ "lamp", "desk" ]
}
` is valid against schema `
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"title": "Product",
"description": "A product from catalog",
"type": "object",
"properties": {
"productId": {
"description": "The unique identifier for a product",
"type": "integer"
},
"productName": {
"type": "string"
},
"price": {
"type": "number",
"exclusiveMinimum": 0
},
"tags": {
"description": "Tags for the product",
"type": "array",
"prefixItems": [{
"type": "string",
"enum": ["lamp", "desk"]
}],
"minItems": 1,
"uniqueItems": true
}
},
"required": [ "productId", "productName", "price", "tags" ]
}
`
Matchers
Matcher is an object which compares objects against a specific criteria and returns a boolean value indicating whether the match was successful or not.
Embedded matchers, placeholders and expressions can be found on the json-unit library readme.
Array contains any of entries
Validate if actual array contains any of entries from the expected one.
#{json-unit.matches:anyOf}($input)
-
$input
- any string which represents expected array entries
Given I initialize story variable `actual-json` with value `
{
"store":{
"authors":[
{
"name":"Yakub Kolas",
"available":true
},
{
"name":"Uladzimir Karatkevich",
"available":true
}
]
}
}
`
Then JSON element from `${actual-json}` by JSON path `$.store` is equal to `{"book":"#{json-unit.matches:anyOf}[{\"name\":\"Uladzimir Karatkevich\",\"available\":true},{\"author\":\"Yanka Kupala\",\"available\":true}])}"`
As JSON do not support multi line strings if you want to improve readability use escapeJson expression inside matcher |
escapeJson
expressionThen JSON element from `${actual-json}` by JSON path `$.store` is equal to `
{
"book":"#{json-unit.matches:anyOf}#{escapeJson([
{
"name":"Uladzimir Karatkevich",
"available":true
},
{
"author":"Yanka Kupala",
"available":true
}
])}"
}