How to parse JSON responses in Katalon Studio


This is a companion discussion topic for the original entry at https://docs.katalon.com/katalon-studio/tutorials/parse_json_responses.html

Hi,
I am trying to get json result like this parsedJson.get(ā€œFeeDefinitionā€).get(ā€œAgentā€).get(ā€œPercentageā€) but when I use the second get() It gives me a syntax error and when I run in debug mode then I get this message

groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.get() is applicable for argument types: (java.lang.String) values: [Agent]
Possible solutions: get(int), get(int), getAt(java.lang.String), getAt(java.lang.String), grep(), grep()

My JSON is:
> {

      "FeeDefinition": [
        {
          "Constraint": {
            "Floor": 10.0,
            "Ceiling": 10000000.0
          },
          "Agent": {
            "Percentage": 0.0,
            "Fixed": 0.0
          },
          "Sender": {
            "Percentage": 0.0,
            "Fixed": 0.0
          },
          "Receiver": {
            "Percentage": 0.0,
            "Fixed": 0.0
          }
        }
      ],
      "Config": {
        "ValidateOnLoad": false,
        "ServiceDescription": "Safaricom"
      }
    }

Hi Ajmal,

FeeDefinition is an array with one object, so you must select array element and then Agent object.

parsedJson.get(ā€œFeeDefinitionā€).get(0).get(ā€œAgentā€).get(ā€œPercentageā€)

1 Like

Thanks for pointing out the issue <3

Had an issue where the keys in the json array contained ā€˜.ā€™ (period) characters. The JSON parsing groks on this as it assumes youā€™re using array/object sublevels

The workaround is to use the fact that JS is happy to treat objects as arrayable.

So

{
  "status":400,
  "message":"The given data was invalid.",
  "errors":{
    "to.0":"The to.0 must be a valid email address.",
    "to.1":"The to.1 must be a valid email address."
  }
}

can be checked using

WS.verifyElementPropertyValue(response, 'errors["to.0"]', 'The to.0 must be a valid email address.')
WS.verifyElementPropertyValue(response, 'errors["to.1"]', 'The to.1 must be a valid email address.')

Hi. Thanks for providing a great example of how to use jsonslurper.
I have a follow-up question however. I want to use JUnit.Assert to verify the value is present in the array1.
So for example if I want to assert that this is present in the array {"id": "open", "title": "Open File"}

In this block of code

for(def member : array1) {
assertEquals('Open', member.id)
break
}

This assertion is failing, because it encounters the first key:value pair of {"id": "new", "title": "New File"}, which is not what weā€™re looking for. What I would like to happen is my code to loop through the entire array and compare each element to what Iā€™m looking for. If my value is not present in the array, then I would fail my assertion.

Thanks for any input.

i have a feeling such key names are against certain DRAFT## json specā€¦ will check and revert. if i am right, you can open a bug for your development team, if i am wrong ā€¦ i am just wrong

@Aleks

Try the following code as a Test Case

import static org.junit.Assert.*
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import groovy.json.JsonSlurper

def str = '''
[
	{ "id": "new", "title": "New File" },
	{ "id": "Ope", "title": "Opened File" }
]
'''

def slurper = new JsonSlurper()
def array1 = slurper.parseText(str)

for (def member: array1) {
	WebUI.comment("member is ${member}")
}

boolean found = false
for (def member: array1) {
	if (member.id == 'Open') {
		found = true
		break
	}
}
assertTrue("member with id of \'Open\' is not contained", found)

@kazurayam Thank you for your response. Iā€™ve tried the use of if loop to do something similar. I was able to print out the id if it matched the member.id iā€™m looking for. But Iā€™m really interested in utilizing assertEquals specifically, because I like the error messaging it provides on test failures ( expected ā€œsomeValueā€ but got ā€œsomeOtherValueā€). My hope is this will provide less technical staff with better understanding of test failure and faster triage.

@Aleks

I do not think I understand what you want to achieve. But let me show you what I tried.

I made a custom keyword class aleks.AleksAssert with a method boolean aleksAssertKeyContained(String message, String keyName, String keyValue, def array):

package aleks

import static org.junit.Assert.*

import com.kms.katalon.core.annotation.Keyword

class AleksAssert {
	
	@Keyword
	static boolean aleksAssertKeyContained(String message, 
			String keyName, String keyValue, def array) {
		boolean found = false
		for (def member: array) {
			if (member[keyName] == keyValue) {
				found = true
				break
			}
		}
		assertTrue(message + " in ${array}", found)
	}
}

I made a Test Case which calls the above mentioned class/method.

import static aleks.AleksAssert.*

import groovy.json.JsonSlurper

def str = '''
[
	{ "id": "new", "title": "New File" },
	{ "id": "ope", "title": "Opened File" }
]
'''

def slurper = new JsonSlurper()
def array1 = slurper.parseText(str)

def keyName = 'id'
def keyValue = 'open'

// call custom keyword
aleksAssertKeyContained("member with ${keyName}=\'${keyValue}\' is not contained",
	keyName, keyValue, array1)

When I ran the test case, I got the following assertion error message:

06-04-2019 10:25:36 午前 Test Cases/TC2

Elapsed time: 0.332s

aleks.AleksAssert.aleksAssertKeyContained:19

Test Cases/TC2 FAILED.
Reason:
java.lang.AssertionError: member with id='open' is not contained in [[id:new, title:New File], [id:ope, title:Opened File]]
	at org.junit.Assert.fail(Assert.java:88)
	at org.junit.Assert.assertTrue(Assert.java:41)
	at org.junit.Assert$assertTrue.callStatic(Unknown Source)
	at aleks.AleksAssert.aleksAssertKeyContained(AleksAssert.groovy:19)
	at TC2.run(TC2:19)
	at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
	at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
	at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:337)
	at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:328)
	at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:307)
	at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:299)
	at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:233)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:114)
	at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:105)
	at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
	at TempTestCase1559611534666.run(TempTestCase1559611534666.groovy:21)

I thought the following line may look favorable for your less technical staff, so I posted this:

aleksAssertKeyContained("member with ${keyName}=\'${keyValue}\' is not contained",
	keyName, keyValue, array1)
1 Like

Assert-Keywords plugin is available.

The methods provided by this plugin can accept a string as the message when failed: e.g; https://github.com/mytt221/katalon-studio-assert-custom-keyword-plugin/blob/master/Scripts/Sample_StringAssert/Script1551856150092.groovy
You might be interested.

1 Like

@kazurayam
Thank you for taking the time to break it down like this. I was hoping to avoid having to go the route of creating my own keywords. Thanks for suggesting the plugin, I didnā€™t think to check the store if that existed, Iā€™ll see if that helps. Thanks again!

Hi,
Please follow below json parsing tutorial

The Simple Way to Parse JSON Responses Using Groovy and Katalon Studio
{ā€œmenuā€: { ā€œidā€: ā€œfileā€, ā€œtoolsā€: { ā€œactionsā€: [ ā€¦
import groovy. json. JsonSlurper. String jsonString = ā€˜ā€™ā€™{ā€œmenuā€: { ā€¦
import com. kms. katalon. core. ā€¦
boolean isKeyPresent = parsedJson. get(ā€œmenuā€ keySet(). ā€¦
def array1 = parsedJson. menu. tools.