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.