JMESPath is a query language for JSON. Examples and a JMESPath tutorial can be found at the JMESPath site. It is used by the field code Action response details and the JWT parser function getFromJSON().
We describe how to get data from JSON objects which are returned as response from an action in after sending a REST request defined by the Atlassian Jira REST API.
We introduce the main search terms that allow you to extract the relevant information from a response. For more complex ones, please have a look at the JMESPath specification.
{ "firstLevelAttribute": "This is the value of a first level attribute", "boolean": true, "jsonAttribute": { "firstName": "John", "lastName": "Doe" }, "emptyList": [], "emptyJSON": { }, "number": 42, "null": null, "listWithJSON": [ { "key": "1", "name": "Sue", "city": "Sydney" }, { "key": "2", "name": "Jeff", "city": "Washington" }, { "key": "3", "name": "Sergej", "city": "Sydney", }, { "key": "4", "name": "Ayse", "city": "Washington", } ], "listWithComplexJSON": [ { "key": "1", "name": { "first": [ "Tom", "Bob" ], "last": "Miller" } }, { "key": "2", "name": { "first": [ "John", "Jane" ], "last": "Doe" } } ], "differentNameStructure": [ { "key": "value1", "name": { "first": [ "Tom", "Bob" ], "last": "Miller" } }, { "key": "value2", "person": { "first": [ "John", "Jane" ], "last": "Doe" } } ] }
you can access the values as described in the table below.
What to get | JMESPath | Example | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Attributes on the first level | Use the name of the attribute. |
| |||||||||||||||||||||||||||
Attributes on a lower JSON level | Use the path to this attribute. |
| |||||||||||||||||||||||||||
Access a certain element of a list attribute | Use the index of the list |
| |||||||||||||||||||||||||||
Get attributes of all list elements | Use the * instead of an index and add the attribute name/path |
| |||||||||||||||||||||||||||
Get a certain attribute of all elements and all level | Use
|
| |||||||||||||||||||||||||||
Filter data | Add a comparison as index for an array |
| |||||||||||||||||||||||||||
Compose new JSON out of the existing one | Add the structure of the new JSON |
| |||||||||||||||||||||||||||
Attribute is not available | If an attribute/path is entered which does not exist in the JSON, null is returned |
|
JMESPath is used by the field code Action response details and the parser function getFromJSON().
Syntactic rules
Escaping certain characters
When used in Action response details, the curly brackets have to be escaped:
character | escaped character |
---|---|
{ | \{ |
} | \} |
Example:
%{action.response.listWithComplexJSON[].\{"fullname":name.last\}}
When used in getFromJSON(), the quote has to be escaped
character | escaped character |
---|---|
" | \" |
Example:
The custom field with the custom ID 10010 holds the value
"listWithComplexJSON": [ { "key": "1", "name": { "first": [ "Tom", "Bob" ], "last": "Miller" } }, { "key": "2", "name": { "first": [ "John", "Jane" ], "last": "Doe" } } ]
%{getFromJSON(%{issue.cf10010},"listWithComplexJSON[].{\"fullname\":name.last}")}
Parser expressions in JMESPath
Conversion from JSON types to string
They always return a text, e.g. the boolean value true
will be converted to the string value true
, an array with elements of a flat data type (e.g. number) will be a comma separated string of the array elements. The null
value is represented as an empty text.
If the result is not
null
boolean
string
number
but a JSON object itself, this JSON object will be converted to a text with JSON.stringify
The same is done if an array does not hold flat values but JSON objects.
These results may be stored in a custom field and being read with the new parser function getFromJSON() in a different post function.
Cast the text results
In case the result is not a text but e.g. a number or an array, you can cast it using the known functions from the parser like toNumber() or toStringList() and used as input for other parser functions or to set a field in post function like Create issue.
JWT parser expression | Result | Note |
---|---|---|
%{toStringList(%{action.response.fields.fixVersions[*].name})} | v2,v5 | |
%{first(toStringList(%{action.response.fields.fixVersions[*].name})} | v2 | This is equivalent to %{action.response.fields.fixVersions[0].name} |
%{toNumber(%{action.response.fields.customfield_10042})} | 21 |
The following JSON is an excerpt of the response returned by a GET /rest/api/3/issue call for issue PU-670
{
"id": "11986",
"self": "https://your-domain.atlassian.net/rest/api/2/issue/11986",
"key": "PU-670",
"fields": {
"summary": "Get the data from the database",
"labels": [
"Backend",
"Frontend"
],
"creator": {
"self": "https://your-domain.atlassian.net/rest/api/2/user?accountId=557058%3A145e0983-5707-439c-80e4-1160dd57f113",
"accountId": "557058:145e0983-5707-439c-80e4-1160dd57f143",
"emailAddress": "not.me@decadis.de",
"avatarUrls": {
"48x48": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/557058:145e0983-5707-439c-80e4-1160d57f114/9f9c7a9a-460d-41e2-825e-859866ae81c6/48",
"24x24": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/557058:145e0983-5707-439c-80e4-1160d57f114/9f9c7a9a-460d-41e2-825e-859866ae81c6/24",
"16x16": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/557058:145e0983-5707-439c-80e4-1160d57f114/9f9c7a9a-460d-41e2-825e-859866ae81c6/16",
"32x32": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/557058:145e0983-5707-439c-80e4-1160d57f114/9f9c7a9a-460d-41e2-825e-859866ae81c6/32"
},
"displayName": "Who am I",
"active": true,
"timeZone": "Europe/Berlin",
"accountType": "atlassian"
},
"statuscategorychangedate": "2021-11-11T00:58:58.197-1100",
"fixVersions": [
{
"self": "https://your-domain.atlassian.net/rest/api/2/version/10003",
"id": "10003",
"description": "",
"name": "v2",
"archived": false,
"released": true,
"releaseDate": "2020-04-28"
},
{
"self": "https://your-domain.atlassian.net/rest/api/2/version/10006",
"id": "10006",
"description": "",
"name": "v5",
"archived": false,
"released": false
}
],
"issuelinks": [
{
"id": "10292",
"self": "https://your-domain.atlassian.net/rest/api/2/issueLink/10292",
"type": {
"id": "10000",
"name": "Blocks",
"inward": "is blocked by",
"outward": "blocks",
"self": "https://your-domain.atlassian.net/rest/api/2/issueLinkType/10000"
},
"outwardIssue": {
"id": "12013",
"key": "PU-684",
"self": "https://your-domain.atlassian.net/rest/api/2/issue/12013",
"fields": {
"summary": "a",
"status": {
"self": "https://your-domain.atlassian.net/rest/api/2/status/10001",
"description": "",
"iconUrl": "https://your-domain.atlassian.net/",
"name": "To Do",
"id": "10001",
"statusCategory": {
"self": "https://your-domain.atlassian.net/rest/api/2/statuscategory/2",
"id": 2,
"key": "new",
"colorName": "blue-gray",
"name": "To Do"
}
},
"priority": {
"self": "https://your-domain.atlassian.net/rest/api/2/priority/3",
"iconUrl": "https://your-domain.atlassian.net/images/icons/priorities/medium.svg",
"name": "Medium",
"id": "3"
},
"issuetype": {
"self": "https://your-domain.atlassian.net/rest/api/2/issuetype/10003",
"id": "10003",
"description": "A small piece of work that's part of a larger task.",
"iconUrl": "https://your-domain.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium",
"name": "Sub-task",
"subtask": true,
"avatarId": 10316,
"hierarchyLevel": -1
}
}
}
},
{
"id": "10292",
"self": "https://your-domain.atlassian.net/rest/api/2/issueLink/10292",
"type": {
"id": "10000",
"name": "Blocks",
"inward": "is blocked by",
"outward": "blocks",
"self": "https://your-domain.atlassian.net/rest/api/2/issueLinkType/10000"
},
"outwardIssue": {
"id": "12013",
"key": "PU-685",
"self": "https://your-domain.atlassian.net/rest/api/2/issue/12013",
"fields": {
"summary": "a",
"status": {
"self": "https://your-domain.atlassian.net/rest/api/2/status/10001",
"description": "",
"iconUrl": "https://your-domain.atlassian.net/",
"name": "To Do",
"id": "10001",
"statusCategory": {
"self": "https://your-domain.atlassian.net/rest/api/2/statuscategory/2",
"id": 2,
"key": "new",
"colorName": "blue-gray",
"name": "To Do"
}
},
"priority": {
"self": "https://your-domain.atlassian.net/rest/api/2/priority/3",
"iconUrl": "https://your-domain.atlassian.net/images/icons/priorities/medium.svg",
"name": "Medium",
"id": "3"
},
"issuetype": {
"self": "https://your-domain.atlassian.net/rest/api/2/issuetype/10003",
"id": "10003",
"description": "A small piece of work that's part of a larger task.",
"iconUrl": "https://your-domain.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium",
"name": "Sub-task",
"subtask": true,
"avatarId": 10316,
"hierarchyLevel": -1
}
}
}
},
{
"id": "10292",
"self": "https://your-domain.atlassian.net/rest/api/2/issueLink/10292",
"type": {
"id": "10000",
"name": "Blocks",
"inward": "is blocked by",
"outward": "blocks",
"self": "https://your-domain.atlassian.net/rest/api/2/issueLinkType/10000"
},
"inwardIssue": {
"id": "12013",
"key": "PU-677",
"self": "https://your-domain.atlassian.net/rest/api/2/issue/12013",
"fields": {
"summary": "a",
"status": {
"self": "https://your-domain.atlassian.net/rest/api/2/status/10001",
"description": "",
"iconUrl": "https://your-domain.atlassian.net/",
"name": "To Do",
"id": "10001",
"statusCategory": {
"self": "https://your-domain.atlassian.net/rest/api/2/statuscategory/2",
"id": 2,
"key": "new",
"colorName": "blue-gray",
"name": "To Do"
}
},
"priority": {
"self": "https://your-domain.atlassian.net/rest/api/2/priority/3",
"iconUrl": "https://your-domain.atlassian.net/images/icons/priorities/medium.svg",
"name": "Medium",
"id": "3"
},
"issuetype": {
"self": "https://your-domain.atlassian.net/rest/api/2/issuetype/10003",
"id": "10003",
"description": "A small piece of work that's part of a larger task.",
"iconUrl": "https://your-domain.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium",
"name": "Sub-task",
"subtask": true,
"avatarId": 10316,
"hierarchyLevel": -1
}
}
}
}
],
"subtasks": [
{
"id": "12193",
"key": "PU-805",
"self": "https://your-domain.atlassian.net/rest/api/3/issue/12193",
"fields": {
"summary": "one",
"status": {
"self": "https://your-domain.atlassian.net/rest/api/3/status/10001",
"description": "",
"iconUrl": "https://your-domain.atlassian.net/",
"name": "To Do",
"id": "10001",
"statusCategory": {
"self": "https://your-domain.atlassian.net/rest/api/3/statuscategory/2",
"id": 2,
"key": "new",
"colorName": "blue-gray",
"name": "To Do"
}
},
"priority": {
"self": "https://your-domain.atlassian.net/rest/api/3/priority/3",
"iconUrl": "https://your-domain.atlassian.net/images/icons/priorities/medium.svg",
"name": "Medium",
"id": "3"
},
"issuetype": {
"self": "https://your-domain.atlassian.net/rest/api/3/issuetype/10003",
"id": "10003",
"description": "A small piece of work that's part of a larger task.",
"iconUrl": "https://your-domain.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10316?size=medium",
"name": "Sub-task",
"subtask": true,
"avatarId": 10316,
"hierarchyLevel": -1
}
}
},
{
"id": "12194",
"key": "PU-806",
"self": "https://your-domain.atlassian.net/rest/api/3/issue/12194",
"fields": {
"summary": "two",
"status": {
"self": "https://your-domain.atlassian.net/rest/api/3/status/10001",
"description": "",
"iconUrl": "https://your-domain.atlassian.net/",
"name": "To Do",
"id": "10001",
"statusCategory": {
"self": "https://your-domain.atlassian.net/rest/api/3/statuscategory/2",
"id": 2,
"key": "new",
"colorName": "blue-gray",
"name": "To Do"
}
},
"priority": {
"self": "https://your-domain.atlassian.net/rest/api/3/priority/3",
"iconUrl": "https://your-domain.atlassian.net/images/icons/priorities/medium.svg",
"name": "Medium",
"id": "3"
},
"issuetype": {
"self": "https://your-domain.atlassian.net/rest/api/3/issuetype/10015",
"id": "10015",
"description": "A very small piece of work that's part of a larger task.",
"iconUrl": "https://your-domain.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10338?size=medium",
"name": "Small Sub-task",
"subtask": true,
"avatarId": 10338,
"hierarchyLevel": -1
}
}
}
]
},
"customfield_10050": {
"self": "https://your-domain.atlassian.net/rest/api/3/user?accountId=5fb3d09bf8b01200694cffb1",
"accountId": "5fb3d09bf8b01200694cffb1",
"avatarUrls": {
"48x48": "https://secure.gravatar.com/avatar/29d7f88795ae29f2ce7b66e42005f49?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU-1.png",
"24x24": "https://secure.gravatar.com/avatar/29d7f88795ae29f2ce7b66e42005f49?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU-1.png",
"16x16": "https://secure.gravatar.com/avatar/29d7f88795ae29f2ce7b66e42005f49?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU-1.png",
"32x32": "https://secure.gravatar.com/avatar/29d7f88795ae29f2ce7b66e42005f49?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FU-1.png"
},
"displayName": "The cutest user",
"active": true,
"timeZone": "Pacific/Midway",
"accountType": "atlassian
},
"customfield_10042": 21
}
The following table using the field code Action response details.
What to get | JMESPath | Result |
---|---|---|
Issue key | %{action.response.key} | PU-670 |
Display name of the creator | %{action.response.fields.creator.displayName} | Who am I |
Atlassian account Id from a single user picker custom field | %{action.response.fields.customfield_10050.accountId} | 5fb3d09bf8b01200694cffb1 |
Get all labels | %{action.response.fields.labels} | Backend,Frontend |
Get the second label | %{action.response.fields.labels[0]} | Frontend |
Get all sub-tasks | %{action.response.subtasks} |
|
Get the first sub-task | %{action.response.fields.subtasks[0]} |
|
Get the names of all fix versions | %{action.response.fields.fixVersions[*].name} | v2,v5 |
Get the keys of all linked issues | %{action.response.fields.issuelinks[*].*.key[]} | PU-684, PU-685, PU-677 The second * eases the access to all linked issues, independent of the direction ( |
Filter the sub-tasks by their issuetype and return the sub-task's summary and the status | %{action.response.fields.subtasks[?fields.issueType.name == 'Sub-task'].\{"summarySub-task": fields.summary, "statusSub-Task": fields.status.name\}} | {"summarySub-task":"one","statusSub-Task":"To Do"} |
If you still have questions, feel free to refer to our support team.