Capture Response id from "PUT" REST API

I have a REST API (PUT) and included the following on my script:

// Create a new test execution instance
def create_test_execution = WS.sendRequest(findTestObject(‘JIRA/ZAPI-Update Execution Details’, [(‘projectId’) : GlobalVariable.JIRA_Project_ID
, (‘cycleId’) : ‘-1’, (‘issueId’) : json_create_issue.id
, (‘assigneeType’) : ‘asignee’, (‘asignee’) : ‘sysadmin’, (‘authorization’) : GlobalVariable.JIRA_Authorisation, (‘url’) : GlobalVariable.JIRA_URL]))

def json_create_test_execution = jsonSlurper.parseText(create_test_execution.getResponseText())

It returns java.lang.IllegalArgumentException: Text must not be null or empty

I am trying to captue the response details such as the JIRA ID.

When I ran the script (not via Test case) but via the API request and Verify method, the response shows 200 and the specific ID.

What is the response code if you send the request via script?

create_test_execution.getStatusCode()

1 Like

The status is 200. It just doesn’t seem to capture the details of the Response text using the PUT method. It works for POST method which I used for another functionality of creating a JIRA test case:

  // Create a new test case with provided information - this needs to be done once		
  def create_issue = WS.sendRequest(findTestObject('JIRA/Create Issue Type', [('projectKey') : GlobalVariable.JIRA_Project_Key
  			, ('summary') : currentTestCaseName, ('description') : 'Creating of an issue using project keys and issue type names using the REST API'
  			, ('issueType') : 'Test', ('priority') : 'Major', ('authorization') : GlobalVariable.JIRA_Authorisation, ('url') : GlobalVariable.JIRA_URL]))
  
  **def json_create_issue = jsonSlurper.parseText(create_issue.getResponseText())**

Exactly which Jira API you are using? Could you take a screenshot of the expected result?

I am actually using ZAPI (Zephyr API plug-in) for JIRA. So I was using the REST API below:
https://getzephyr.docs.apiary.io/#reference/executionresource/update-execution-details/update-execution-details

When I run it via the Web object screen (Request and Verify), it shows exactly what I needed (with status 200) similar to the below:

{
“id”: 49,
“orderId”: 21,
“executionStatus”: “3”,
“executedOn”: “Today 2:10 PM”,
“executedBy”: “vm_admin”,
“executedByDisplay”: “vm_admin”,
“comment”: “”,
“htmlComment”: “”,
“cycleId”: 51,
“cycleName”: “c1”,
“versionId”: -1,
“versionName”: “Unscheduled”,
“projectId”: 10100,
“createdBy”: “vm_admin”,
“modifiedBy”: “vm_admin”,
“issueId”: 10400,
“issueKey”: “HTC-1”,
“summary”: “test1”,
“label”: “”,
“component”: “”,
“projectKey”: “HTC”
}

In the Response above, I’d like to get the value of “id” which is 49.

However, the code below throws me an error that the Text is null or empty:

def json_create_test_execution = jsonSlurper.parseText(create_test_execution.getResponseText())
String testId = json_create_test_execution.id

Ok I got it. I mistakenly (or stup*dly) was calling the incorrect API. Thanks for the effort looking into it though @Brian_Ducson

@Brian_Ducson Ok I got another problem (which still applies to the original topic I asked earlier) as it is always showing null when I am trying to capture a value from the response body.
So, the response body generated is as follows:

{
“39”: {
“id”: 39,
“name”: Test
}
}

However, when I am trying to display the “id” value using the jsonSlurper, it returns null.

def response_to_print = jsonSlurper.parseText(.getResponseText())
log.logInfo(response_to_print.toString()) –> shows correct as {39={id=39, name=Test}}
log.logInfo(response_to_print.id) –> shows null

Note that “39” is dynamic and not fixed so it keeps changing everytime. As I need to pass this value to test case, then I can’t just hardcode it to “39” so I need to capture the value of “id” or I workaround by using substring to grabe the values before “: {

I am fairly new to automation of API so bare with me if the terms I use are not correct.

To reduce this behavior in the future, JSonPath is suggested to use. Similar to XPath or CSS locators of a WebElement, using JSonPath can locate the response’s node:
https://docs.katalon.com/katalon-studio/tutorials/verify-api-responses.html#verifying-rest-response-in-json-format

import groovy.json.JsonSlurper

def jsonSlurper = new JsonSlurper()

def y = jsonSlurper.parseText(x)

def key = y.keySet()[0]

println y.get(key).get(id)

Hi Vinh, I use this most of the time but since the parent node is dynamic, I cannot pass this as a variable.
the jSonPath will keep changing (e.g. 30.id then when I run the script again, the response will change to 31.id, 32.id, and so on and so forth).

Thanks Brian, thanks for this. I got it working using the below:

def jsonSlurper = new JsonSlurper()
def create_test_execution = WS.sendRequest(findTestObject(’…’)
def json_create_test_execution = jsonSlurper.parseText(create_test_execution.getResponseText())

//skip the parent value in ZAPI as it is always dynamic
def (rootKey, testExecutionId) = json_create_test_execution.findResult { k, v -> [k, v.id] }

2 Likes

Hi @Brian_Ducson , would you know how to skip two levels of dynamic values?
I need to retrieve the 3rd level value by ignoring the parent level (which is always dynamic) and the 2nd level which is unfortunately, also dynamic. Response body below:

{
1”:[
{
8”:{
“totalExecutions”:0,
}

From above, I need to skip “1” and “8” (both will dynamically change) before retrieving the value “0” of totalExecutions. I tried following the nested loop statement from here (putting another loop statement within the loop:
https://forum.katalon.com/t/how-to-get-json-value-skip-first-level/10857/6

but I get the error below:
com.kms.katalon.core.exception.StepErrorException: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object ‘1=[{8={totalExecutions=0}]’ with class ‘java.util.TreeMap$Entry’ to class 'java.util.Map’

@Zarashima any ideas on this? :slight_smile:

@Evan, can you provide your script?

1 Like

I was just checking the 2nd level at this stage, but getting the error already as it seems not able to identify the Map variable:

def search_test_cycle = WS.sendRequest(findTestObject(‘JIRA/ZAPI-Get List of Cycle’, [(‘authorization’) : GlobalVariable.JIRA_Authorisation, (‘projectId’) : GlobalVariable.JIRA_Project_ID
, (‘url’) : GlobalVariable.JIRA_URL, (‘versionId’) : ‘’, (‘cycleId’) : ‘’, (‘issueId’) : ‘’])) –> the response body for this is the above {“1”:[{8”:{totalExecutions”:0}

def json_search_test_cycle = jsonSlurper.parseText(search_test_cycle.getResponseText())
KeywordUtil.logInfo(json_search_test_cycle.toString())
def d = json_search_test_cycle.keySet()[0]

for (Map map : json_search_test_cycle){
Set keySet = map.keySet()
Iterator iter = keySet.iterator()
while (iter.hasNext()) {
def key = iter.next()
def v = map.get(key)
KeywordUtil.logInfo(v.toString())
}
}

anyone? :slight_smile:

The object is not a Map, but a Map.Entry, i.e. a key-value pair (think of Map as a Set of key-value pairs). Let’s say we have a map m:

{
"1":[
{
"8":{
“totalExecutions”:0,
}

you can try

def firstLevel = m.firstEntry().getValue()
def secondLevel = firstLevel[0].firstEntry().getValue()

I didn’t try the code myself - if you encounter problems don’t hesitate to let me know.

See https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html#firstEntry for more details.

1 Like