JSON JMESPath Extractor
Table of Contents
Intermediate - This article is part of a series.
What is JMESPath ? #
JMESPath was developed in 2012 by James Saryerwinnie, an engineer at Mozilla Corporation, as a alternative to JSONPath for accessing and manipulating data in JSON documents. The main motivation behind the creation of JMESPath was to create a more efficient and flexible tool for accessing data in JSON documents that are widely used in web and mobile applications.
In the following years, JMESPath became increasingly popular among developers working with web and mobile applications that use JSON as a data exchange format. It was integrated into several popular Python libraries and tools, becoming an essential tool for managing cloud infrastructure. In 2017, JMESPath became an open-source project under the Python projects organization. Since then, it has been adopted by various Python libraries and tools such as AWS CLI and Terraform, used in a variety of contexts, from data analysis to system integration and process automation.
Today, JMESPath remains a popular tool for accessing and manipulating data in JSON documents used in web and mobile applications. It is compatible with a wide variety of programming languages and frameworks, and is used across various contexts such as cloud infrastructure management, data analysis, and process automation.
What is JSON? #
JSON (JavaScript Object Notation) is a lightweight text format for efficient data exchange. It is commonly used to transmit information between an application client and server or to transmit data between applications. JSON represents data in the form of nested objects and lists of objects, using a clear and easy-to-read syntax based on keys { } to define objects and brackets [ ] to define lists.
{
"nombre": "Ana",
"edad": 28,
"direccion": {
"calle": "Calle Principal",
"ciudad": "Ciudad de México",
"estado": "Ciudad de México",
"codigo_postal": "12345"
},
"intereses": ["leer","viajar","cocinar"]
}
Attribute | Description | Required |
---|---|---|
Name | Descriptive name for this element that is displayed in the tree. | Not |
Apply to | Useful when used with mappers that can generate sub-samples, such as HTTP sampler with embedded resources, Mail Reader or transaction controller generated samples. Main sample only: applies only to main sample Sub-samples only: applies only to sub-samples Main and sub-samples: applies to both Variable name used in JMeter: extraction will be applied to the content of the named variable | Yes |
Created Variable Name | The name of the JMeter variable where the result will be stored. | Yes |
JMESPath Expressions | Query element using JMESPath language. Can return the matching result. 0: random selection -1: all results (default), named as <variable name>_N where N is from 1 to number of results X: extract X th result (where X is greater than number of matches, default value) | Not |
Default Number of Matches (0 for random) | If JMESPath query has many results, you can choose which ones to extract as variables: 0: random selection -1: all results (default), named as <variable name>_N where N is from 1 to number of results X: extract X th result (where X is greater than number of matches, default value) | Not |
Default Value | Default value returned when no match found. Also returns if node has no value and fragment option not selected. | Not |
{
"nombre": "Ana",
"edad": 28,
"direccion": {
"calle": "Calle Principal",
"ciudad": "Ciudad de México",
"estado": "Ciudad de México",
"codigo_postal": "12345"
},
"intereses": ["leer","viajar","cocinar"]
}
nombre //Ana
edad //28
direccion.calle //Calle Principal
direccion.codigo_postal //12345
direccion.ciudad //Ciudad de México
hobbies //["leer","viajar","cocinar"]
What other usage examples might JMESPath have? #
Let’s consider a more complex example, like the following:
[{
"name": "John Doe",
"age": 35,
"address": {
"street": "123 Main St",
"city": "Anytown",
"state": "WA"
},
"phoneNumbers": [
{
"type": "mobile",
"number": "555-551-1234"
},
{
"type": "home",
"number": "555-552-5678"
}
],
"email": "john.doe@example.com"
},{
"name": "Peter Doe",
"age": 34,
"address": {
"street": "123 Second St",
"city": "RacconCity",
"state": "TX"
},
"phoneNumbers": [
{
"type": "mobile",
"number": "555-553-1234"
},
{
"type": "home",
"number": "555-554-5678"
}
],
"email": "peter.doe@example.com"
},{
"name": "Rick Doe",
"age": 36,
"address": {
"street": "123 Third St",
"city": "Springfield",
"state": "NJ"
},
"phoneNumbers": [
{
"type": "mobile",
"number": "555-555-1234"
},
{
"type": "home",
"number": "555-556-5678"
}
],
"email": "rick.doe@example.com"
}]
For this example, suppose we want to evaluate and extract the following data:
Expression | Result |
---|---|
[*].name | returns all the names of the people. |
[0].phoneNumbers[0].number | returns the mobile phone number of the first phoneNumbers object. |
[?address.state=='WA'].name | returns the names of people whose state is WA. |
[*].phoneNumbers[?type=='mobile'].number | returns the mobile phone numbers of the phoneNumbers objects. |
length([*].phoneNumbers[?type=='home']) | returns the number of phoneNumbers objects of type home. |
sort_by(@, &age)[0].name | Returns the name of the youngest person. |
sort_by(@, &age)[-1].name | Returns the name of the oldest person. |
max_by(@, &age).name | Returns the name of the oldest person. |
min_by(@, &age).name | Returns the name of the youngest person. |
[*].name | sort(@) | Returns a list of people’s names in alphabetical order. |
sum([*].age) | Returns the sum of all ages. |
length([*].phoneNumbers) | Returns the number of phone numbers. |
join(', ', [*].phoneNumbers[].number) | Returns a string containing a list of all phone numbers. |
[?age >= `35` ] | Returns the names of people whose age is greater than 35. |
[?age >= `35`] | [?address.state == ‘WA’].name | Returns the names of people over the age of 35 who live in WA. |
[?contains(email,'john')].email | [0] | Returns the email address of the person whose name contains john. |
[?contains(name, 'Doe')].phoneNumbers[].number | [1] | Returns the second phone number of people whose name contains Doe. |
[?address.state=='TX'].address.city | sort(@) | [0] | Returns the name of the smallest city in Texas. |
[*].name | reverse(@) | Returns the names of people from oldest to youngest. |
[*].age | sum(@) | returns the sum of all ages. |
To evaluate these sentences, I recommend using a receiver View results tree and use the view in JSON JMESPath Tester. Introduce the sentence into the field JMESPath Expression, then click on the button Test.
Conclusion #
JMESPath is a very powerful tool for extracting values, multiple values, evaluation or execution of functions from the values to satisfy one or more criteria, always remember to practice before developing your sentence or expression. It’s always good to verify the criteria with different types of responses to obtain conclusive results. You need to practice until next time!