JMESPath

JMESPath is a query language for JSONExamples 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.

How to work with JMESPath in general

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.

If an action return this JSON
JavaScript
{
  "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.


JMESPath

Result

Notes

firstLevelAttribute

This is the value of a first level attribute


jsonAttribute

{ "firstName": "John","lastName": "Doe" }


emptyList


The empty list is converted to an empty string

emptyJSON

{}


boolean

true


number

42


null


The null value is converted to an empty string

notExisting


If the attribute does not exist, an empty string is returned



Attributes on a lower JSON level

Use the path to this attribute. 


JMESPath

Result

jsonAttribute.firstName

John


Access a certain element of a list attribute

Use the index of the list


JMESPath

Result

Notes

listWithComplexJSON[0]

{ "key": "1", "name": { "first": [ "Tom", "Bob" ], "last": "Miller" } }

The first element of a list has the index 0

listWithJSON[1]

{ "key": "2", "name": "Jeff" }



Get attributes of all list elements

Use the * instead of an index and add the attribute name/path


JMESPath

Result

Notes

listWithJSON[*].name

Sue,Jeff,Sergej,Ayse


listWithJSON[*]

{ "key": "1", "name": "Sue" }, { "key": "2", "name": "Jeff" }, { "key": "3", "name": "Sergej" }, { "key": "4", "name": "Ayse" }

You can achieve the same result by
listWithJSON

listWithComplexJSON[*].name.last

Miller,Doe



Get a certain attribute of all elements and all level

Use 

[*]and .*. in combination

* in a path means "all values at this level"

[] flattens the result if it is a list (or a list of lists)


JMESPath

Result

Notes

differentNameStructure[*]


[{"key":"value1","name":{"first":["Tom","Bob"],"last":"Miller"}},{"key":"value2","person":{"first":["John","Jane"],"last":"Doe"}}]

Get all elements of the list differentNameStructure

differentNameStructure[*].*

[["value1",{"first":["Tom","Bob"],"last":"Miller"}],
["value2",{"first":["John","Jane"],"last":"Doe"}]]

Now get all elements of the next level (i.e. all values of the "key", "name" and "person" elements)

This is a list of lists

differentNameStructure[*].*.last

[["Miller"],["Doe"]]

Getting only the last names of the structure (if available)

This is still a list of lists (with only one element)

differentNameStructure[*].*.last[]

Miller,Doe

The operator [] flattens the result


Filter data

Add a comparison as index for an array


JMESPath

Result

Notes

listWithJSON[?city == 'Washington']

[{"key":2,"name":"Jeff","city":"Washington"},{"key":4,"name":"Ayse","city":"Washington"}]


listWithJSON[?city == 'Washington' ].{key: key, name:name}

[{"key":2,"name":"Jeff"},{"key":4,"name":"Ayse"}]



Compose new JSON out of the existing one

Add the structure of the new JSON


JMESPath

Result

Notes

listWithJSON.{index: to_string(key), name:name}

[{"index":"1","name":"Sue"},{"index":"2","name":"Jeff"},{"index":"3","name":"Sergej"},{"index":"4","name":"Ayse"}]

Build a different structure where the key is called "index" and is a text and not a number. Leave out the attribute "city". This structure may be requested from a different function.

listWithJSON[?city == 'Washington'].{index: key, name:name}

[{"index":2,"name":"Jeff"},{"index":4,"name":"Ayse"}]

Combine a filter with a structure.


Attribute is not available

If an attribute/path is entered which does not exist in the JSON, null is returned


JMESPath

doesNotExist

firstLevelAttribute.doesNotExist

jsonAttribute.doesNotExist

jsonAttribute.first.doesNotExist

listWithJSON[200]

How to work with JMESPath in JWT expressions

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:

JavaScript
%{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

JavaScript
"listWithComplexJSON": [
    {
      "key": "1",
      "name": {
        "first": [
          "Tom",
          "Bob"
        ],
        "last": "Miller"
      }
    },
    {
      "key": "2",
      "name": {
        "first": [
          "John",
          "Jane"
        ],
        "last": "Doe"
      }
    }
  ]
JavaScript
%{getFromJSON(%{issue.cf10010},"listWithComplexJSON[].{\"fullname\":name.last}")}
Parser expressions in JMESPath

You cannot use JWT field codes or parser expressions in JMESPath itself.

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


How to use JMESPath for a Jira REST API response

The following JSON is an excerpt of the response returned by a GET /rest/api/3/issue call for issue PU-670

Example for the response of a Jira REST API call

{ "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}


List of JSON of the sub-tasks

{ "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 } } }


Get the first sub-task

%{action.response.fields.subtasks[0]}

JSON structure of the first sub-task

{ "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 } } }



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 (inward or outward). [] flattens the result that otherwise would be list of list.


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"}