cancel
Showing results for 
Search instead for 
Did you mean: 

Passing a json node (rather than the node's value) to a Property

SOLVED
Highlighted
Community Hero

Passing a json node (rather than the node's value) to a Property

Hi,

 

I need to grab a node name rather than the value from a .json request and pass it onto a subsequent .json request's body.

 

 

I have 2 api's I need to test.  1 is a POST followed by a GET.  The POST's response body has the same structure as the GETs request body.

 

My POST's api generates the following .json response

 

{
"$id": "1",
"UniqueAlphaNumericGUID": {
"$id": "2",
"StatusCode": 0,
"Outcome": "NewCall"
}
}

As you can see the 'UniqueAlphaNumericGUID' is the label (or json node) AND the value. 

 

SoapUI obviously treats this as the node rather than the value - but it is actually the unique reference of a record <-- so the node name changes for each record

 

I need to do a property transfer of this value to pass onto the GET's request body but I'm unsure how to do this because I need to pass the node name rather than the node's value.

 

@msiadakgave me some groovyscript to parse XML and I tried converting it to parse .json but I'm not going to embaress myself by giving you what I got - its rubbish and doesn't even come close to working.

 

a java developer gave me the following to start me off:

import groovy.json.JsonSlurper
def json = "{\"\$id\": \"1\",\"UniqueAlphaNumericGUID\": {\"\$id\": \"2\", \"StatusCode\": 0,\"Outcome\": \"NewCall\"}}"
def myguid = ""
def test = new JsonSlurper().parseText(json)
println test.keySet()[1]

 

I would welcome any help/hints/advice anyone has!

 

thanks to all!

 

richie

 

 

 

 

 

 

 

if this helped answer the post, could you please mark it as 'solved'? Also if you consider whether the title of your post is relevant? Perhaps if the post is solved, it might make sense to update the title of the post to something more descriptive? This will help people when searching for problems.
2 ACCEPTED SOLUTIONS

Accepted Solutions
Contributor

Re: Passing a json node (rather than the node's value) to a Property

@richie, here is one more method to execute a REST step for multiple UIDs. In this example I have used your response with 3 different UIDs.

 

I saved below response in a text file and reading it from there.

{
   "$id" : "1",
   "1826d9a8-f542-e811-8120-5065f38b0571" : {
      "$id" : "2",
      "StatusCode" : 0,
      "Outcome" : "NewCall"
   },
   "beb19fbb-f542-e811-8120-5065f38b0571" : {
      "$id" : "3",
      "StatusCode" : 0,
      "Outcome" : "NewCall"
   },
   "ffe022cc-f542-e811-8120-5065f38b0571" : {
      "$id" : "4",
      "StatusCode" : 0,
      "Outcome" : "NewCall"
   }
}

groovy script to  extract GUIDs and iterate through them and execute RestTestStep for each GUID.

 

import groovy.json.JsonSlurper

def response = new File("c://users//XXXX//desktop//response.txt").text
def json = new JsonSlurper().parseText response 

def i = 0
def UID = []

json.each{
	     if(it.key !='$id'){
                              UID += it.key	                      
	     }
	     i++
   
}


log.info UID //## Array with 3 unique IDs ##//



def j=0
def uniqueId

UID.each{
	    //##Update TestCase Property with UID ##//
	     uniqueId = UID[j]            
          testRunner.testCase.setPropertyValue("uniqueId", UID[j]) //store in a testcase property and then use this in subsequesnt RestTestStep//
          
          log.info "Executing RestStep for UID- $uniqueId"
          testRunner.runTestStepByName("YourRESTTestStep") // Execute RestStep Here //
j++
}
Community Hero

Re: Passing a json node (rather than the node's value) to a Property

@New2API

 

WOW! - thanks so much!

 

Really appreciate all the effort you made on my behalf!

 

richie!

if this helped answer the post, could you please mark it as 'solved'? Also if you consider whether the title of your post is relevant? Perhaps if the post is solved, it might make sense to update the title of the post to something more descriptive? This will help people when searching for problems.
17 REPLIES 17
Contributor

Re: Passing a json node (rather than the node's value) to a Property

Hi Richie, I assume that you want to read the response from a REST teststep and extract a key from a json node.

 

please check if this helps:

 

I have stored your json response in a text file but you could use 

def response = context.expand( '${'+TestStepName+'#Response}' )

 

import net.sf.json.groovy.*
import groovy.json.JsonSlurper

def response = new File("c:\\users\\xxxxx\\desktop\\response.txt").text //or point to a rest response: def response = context.expand( '${'+TestStepName+'#Response}' )


def json = new JsonSlurper().parseText response

def jNode

 json.each{
 	       if(it.key.contains("GUID")){
 	                                  log.info it.key
 	                                  jNode = it.key
 	                                  //or store it in some property 
 	       }
 }
Contributor

Re: Passing a json node (rather than the node's value) to a Property

Have you tried using the JsonBuilder? 

 

It seems you need a property expansion on the node, in effect making the node a property you can vary. I do property expansions on the value side and don't have a project to test out the concept below but here is an outline that maybe you can try:

 

import groovy.json.JsonBuilder
 
def json = new JsonBuilder()
 
def nodeName = context.expand('${#Project#CPnode_name}').toString()
 
def id1 = "1"
def id2 = "2"
def Outcome = "NewCall"
def StatusCode = "0"
 
def nodeValue = json "$id" : id2,
                           StatusCode : StatusCode,
                           Outcome : Outcome
 
def root = json "$id" : id1,
                 "$nodeName" nodeValue
 
def restRequest = testRunner.testCase.getTestStepByName(" < your test step name > ");
restRequest.setPropertyValue('Request', json.toString())


 

so that you should be able to get the unique alpha numeric ID variable substituted for $nodeName from the expansion.

 

Like I say, I did not test it.

 

 

Community Hero

Re: Passing a json node (rather than the node's value) to a Property

 

@Bill_In_Irvine@New2API,

 

guys - thanks so much - I've tried both options but I'm still struggling so would welcome if you could answer some follow up questions based on your scripts.

 

@Bill_In_Irvine

 

I edited your script as you suggested, but I'm getting a runtime error 

 

The edited script is as follows:

 

import groovy.json.JsonBuilder
 
def json = new JsonBuilder()
def nodeName = context.expand('${#Project#CPnode_name}').toString()
 
def id1 = "1"
def id2 = "2"
def Outcome = "NewCall"
def StatusCode = "0"
 
def nodeValue = json "$id" : id2,
                           StatusCode : StatusCode,
                           Outcome : Outcome
 
def root = json "$id" : id1,
                 "$nodeName" nodeValue
 
def restRequest = testRunner.testCase.getTestStepByName("GET Request - GET EOD Results");
restRequest.setPropertyValue('Request', json.toString())

 

 

 

Runtime error at line 12 which is the line that contains 

 

def nodeValue = json "$id" : id2,

 

The error response is 'MissingPropertyException: No such property: id for class:' 

 

I'm sorry my groovy is rubbish - I've tried playing around with the line and the one before and after it - but I've had no luck.  Can you advise?

 

So - that's the questions for @Bill_In_Irvine all done

 

@New2API

 

I updated your script to the following - but I'm struggling to write the data out to a property - your script is below:

 

import net.sf.json.groovy.*
import groovy.json.JsonSlurper

def responseCntent = context.expand( '${REST Request - GET EOD Results#Response}' )

def json = new JsonSlurper().parseText responseCntent

def jNode

 json.each{
 	       if(it.key.contains("GUID")){
 	                                  log.info it.key
 	                                  jNode = it.key
 	                                  //or store it in some property 
 	       }
 }

 

 

Now I was playing around with something I've used before (courtesy of @msiadak) which assigned a variable to the attribute value I wanted in the XML and allowed me to pass this to the properties step (as follows)

 

 

def syncID = (holder["//Responses/VenueSyncSuccesses/VenueSyncSuccess/@VenueID"])
        def propertiesStep = context.testCase.testSteps["Properties"];
propertiesStep.setPropertyValue("VenueID", syncID);

 

I tried doing something like this for the .json - however - the info response the script currently returns is the whole .json response - I'm failing to see how I can extract ONLY the node names from this - dont I need to parse the .json and grab the GUID node names?  And even then I can't see how something like this would work for my .json because those node names are dynamic based on the records - i.e. the node name changes for each record returned in the results.

 

Also - I cant see what the jNode variable is doing.  It doesn't appear to add anything to the current script nor the script results.

 

as I say - my scripting skills are rubbish so I'm no doubt missing some obvious piece of info.

 

 

Many thanks guys for all your help in this - you're really helping me out here.

 

richie

if this helped answer the post, could you please mark it as 'solved'? Also if you consider whether the title of your post is relevant? Perhaps if the post is solved, it might make sense to update the title of the post to something more descriptive? This will help people when searching for problems.
Contributor

Re: Passing a json node (rather than the node's value) to a Property

Hi Richie,

 

I assumed your POST request generated a json that had the $id in the name. Is the intention something like {id: 12,...} or is it like {12:12...}?  You will need a property expansion to get the value of id2.

 

The contributor New2API has the approach that you probably want - to read the response in a groovy test step following the POST test step.  That way you will get whatever id name/value fields that are generated in the json of the POST response and you might then resolve the exception you got.

 

But I think you still need to splice in the node for 

UniqueAlphaNumericGUI

 

I haven't read your response to New2Api but if you can retrieve  the json response without a problem in that suggested groovy script, just log.info json.toString() and see what it gets you. 

 

You might then create another json variable (as a JsonBuilder object)  to construct a new json expression and copy the pieces from the response. Then splice in the nodeName as I first suggested. That "nodeName:" is the value that you expect changes every time you do a POST.

 

It's kind of ugly, but it's just a concept I have and I have not tried it out. 

 

 

Contributor

Re: Passing a json node (rather than the node's value) to a Property

Hi Richie, in your response you have two json nodes i.e., $id and UniqueAlphaNumericGUID. I assumed that you wanted to extract second node from the response and store it in some property variable.

 

In my script, jNode is a variable used to store that node name. it is defined outside of each loop so that it is not local to each statement.

 

as far as property transfer, please see below script. i have added two more lines. I am storing these values at test suite level in order to be used in different testcases.

 

import net.sf.json.groovy.*
import groovy.json.JsonSlurper

def responseCntent = context.expand( '${REST Request - GET EOD Results#Response}' )

def json = new JsonSlurper().parseText responseCntent

def jNode
def jValue json.each{ if(it.key.contains("GUID")){ log.info it.key
log.info it.value.$id

jNode = it.key
jValue = it.value.$id
context.testCase.testSuite.setPropertyValue("IDName", "$jNode")
context.testCase.testSuite.setPropertyValue("IDVal", "$jValue") } }
Community Hero

Re: Passing a json node (rather than the node's value) to a Property

Hi New2API,

 

You're exactly right - I need to capture the 'UniqueAlphaNumericGUID' value as this is both the node name and the value I need to pass onto subsequent steps.

 

I altered the script as per your instructions (see below)

 

import net.sf.json.groovy.*
import groovy.json.JsonSlurper

def responseCntent = context.expand( '${REST Request - GET TP EOD Results#Response}' )

def json = new JsonSlurper().parseText responseCntent

def jNode
def jValue

json.each{ if(it.key.contains("GUID")){ log.info it.key log.info it.value.$id jNode = it.key jValue = it.value.$id context.testCase.testSuite.setPropertyValue("IDName", "$jNode") context.testCase.testSuite.setPropertyValue("IDVal", "$jValue") } }

Now you state that you set the propertyvalues at TestSuite level so I can transfer them to other test cases within the testsuite.  HOWEVER - I can't see the 'IDName' or 'IDVal' properties on the TestSuite at all. 

 

I tried running the 'GetData' function from another step in my test to point to the TestSuite to see the 'IDName' and 'IDVal' properties that way - but there weren't any properties at TestSuite level.

 

So - I tried changing the script to the following to write the properties to a Properties step and I added ONE log.info (immediately after the 'json each') and FOUR log.info lines outside the 'json.each'

 

import net.sf.json.groovy.*
import groovy.json.JsonSlurper

def responseCntent = new File("d:/NCC Teleperformance/groovysoapuitestfolder/response2.txt").text

def json = new JsonSlurper().parseText responseCntent

def jNode
def jValue

json.each{

log.info(it.key)
if(it.key.contains("GUID")){
log.info(it.key)
log.info(it.value.$id)

jNode = it.key
jValue = it.value.$id

def propertiesStep = context.testCase.testSteps["Properties 1"];
propertiesStep.setPropertyValue("IDName", "$jNode")
propertiesStep.setPropertyValue("IDVal", "$jValue")

}
}

log.info("IDName")
log.info("$jNode")
log.info("IDVal")
log.info("$jValue")

 

When I executed the script the output log returned the following:

 

 

INFO:$id
INFO:UniqueAlphaNumericGUID
INFO:IDName INFO:null INFO:IDVal INFO:null

So - I don't think the properties are being populated - which kinda makes sense when I think about the fact my properties test step doesn't have any properties in it and my TestSuite didn't have any properties on it when before I'd altered the script to write to the Properties step rather than write the properties at TestSuite level.

 

 

 

I'm sorry - I imagine helping me is like trying to teach a 4 year old to read.

 

I understand if you can't provide any more help on this - you've given me plenty of time already - but if you're still feeling generous I'd welcome any hints you've got!

 

Cheers,

 

richie

 

if this helped answer the post, could you please mark it as 'solved'? Also if you consider whether the title of your post is relevant? Perhaps if the post is solved, it might make sense to update the title of the post to something more descriptive? This will help people when searching for problems.
Contributor

Re: Passing a json node (rather than the node's value) to a Property

Hi Richie, I did execute this groovy script on my machine and values are being populated in TestSuite Custom property tab.

 

I further added few more lines to print jNode and jValue. Also, get and print Test Suite property values.

 

import net.sf.json.groovy.*
import groovy.json.JsonSlurper

def responseCntent = context.expand( '${REST Request - GET TP EOD Results#Response}' )

def json = new JsonSlurper().parseText responseCntent

def jNode
def jValue

json.each{
           if(it.key.contains("GUID")){
 	                                  log.info it.key
                                          log.info it.value.$id
 
                                          jNode = it.key
                                          jValue = it.value.$id
                                          context.testCase.testSuite.setPropertyValue("IDName", "$jNode")
                                          context.testCase.testSuite.setPropertyValue("IDVal", "$jValue") 

     }
}


log.info "$jNode"
log.info "$jValue"

//getting values from test Suite
log.info "Property Value from TestSuite IDName: " + context.expand('${#TestSuite#IDName}')
log.info "Property Value from TestSuite IDVal: " + context.expand('${#TestSuite#IDVal}')

TestSuiteProps.PNG

Community Hero

Re: Passing a json node (rather than the node's value) to a Property

Weird!

 

It's not working - it works where you are - but isn't working for me here!

 

I did exactly what you did - I created a new empty project, a new testsuite, a new testcase and a single groovyteststep. 

 

I copied the groovyscript text from your post and pasted it straight into my groovystep.  The only change I made (so you can see the results in the image) is that I pointed the responseCntent variable to a file on the harddrive (which contains only the .json I am using).  I have attached the file with the .json results so you can see.  I have also tried pointing the responseCntent variable to the REST request results (which contains the relevant .json) but that didn't work.

 

As you can see from the image I posted - the IDVal and IDName properties are not being written to the TestSuite and you can see from the logging output - those properties are empty!

 

I am beginning to wonder if this is an environment issue - can you confirm what version of java and ReadyAPI! you are using please? 

 

I am running Java v1.8.0_144 with ReadyAPI! v2.3.0.   Think my next point is to contact SmartBear.  Thankyou!

 

New2API.PNG

if this helped answer the post, could you please mark it as 'solved'? Also if you consider whether the title of your post is relevant? Perhaps if the post is solved, it might make sense to update the title of the post to something more descriptive? This will help people when searching for problems.
Contributor

Re: Passing a json node (rather than the node's value) to a Property

Richie... I am still using RadyAPI 2.2. 

can see if you any output for log.info json? if not then as one of the user suggested json slurper is deprecated in v2.3.

 

https://community.smartbear.com/t5/SoapUI-Pro/JsonSlurper-no-longer-available-in-2-3-0-Solution-Json...

 

Please modify the script to use JsonUtil.parseTrimmedText() and see if this make any difference.

New Here?
Join us and watch the welcome video:
Top Kudoed Authors