# How do I verify a value buried deep inside a JSON response?

**URL:** <https://forum.katalon.com/t/how-do-i-verify-a-value-buried-deep-inside-a-json-response/190370>\
**Category:** Web Testing\
**Created:** [April 25, 2026, 11:39am UTC](https://forum.katalon.com/t/how-do-i-verify-a-value-buried-deep-inside-a-json-response/190370 "2026-04-25T11:39:28Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![ebauch](https://dub1.discourse-cdn.com/katalon/user_avatar/forum.katalon.com/ebauch/32/33812_2.png) [@ebauch](https://forum.katalon.com/u/ebauch)\
**Post date:** [April 25, 2026, 11:39am UTC](https://forum.katalon.com/t/how-do-i-verify-a-value-buried-deep-inside-a-json-response/190370/1 "2026-04-25T11:39:28Z")

</div>

I’m trying to verify my API response, but the JSON I get back is a total mess of brackets and braces. I can see the `accountBalance` value when I look at the response in the “Console” or “Log Viewer,” but I don’t know how to tell Katalon to go find it.

The JSON isn’t just a simple list; it’s nested! It looks something like `data`, then inside that is `accountDetails`, and then inside _that_ is an array of objects, and the balance is inside one of those. I tried using `WS.verifyElementPropertyValue`, but I keep getting errors like “Expected value is null” because I’m definitely not typing the path correctly. Is there an easier way to “drill down” into these layers without guessing the path every time?

---

<div class="post-metadata">

**Author:** ![qurzunta.kaab](https://dub1.discourse-cdn.com/katalon/user_avatar/forum.katalon.com/qurzunta.kaab/32/31470_2.png) [@qurzunta.kaab](https://forum.katalon.com/u/qurzunta.kaab)\
**Post date:** [April 25, 2026, 11:44am UTC](https://forum.katalon.com/t/how-do-i-verify-a-value-buried-deep-inside-a-json-response/190370/2 "2026-04-25T11:44:35Z")

</div>

Navigating nested JSON structures is a fundamental skill in API automation. To do this reliably, we use **GPath** (Groovy Path) expressions. Think of GPath as “XPath for JSON.”

Instead of guessing the path, you should use the **Object Repository’s “Verification” tab** or a dedicated JSON parser. In professional testing, we use `JsonSlurper` to turn that “mess of brackets” into a searchable Map/List structure. This allows us to use dot notation (e.g., `data.account.balance`) to reach any depth.

### **The Solution: Using GPath and JsonSlurper**

If your JSON looks like this:

JSON

```auto
{
  "data": {
    "accountDetails": [
      { "type": "Savings", "balance": 5000.00 }
    ]
  }
}

```

Your path is: `data.accountDetails[0].balance`

### **Custom Keyword Helper: The JSON Navigator**

This keyword allows you to pass a “dot-notation” path (like a GPS coordinate) to find any value within your API response instantly.

Groovy

```auto
import com.kms.katalon.core.annotation.Keyword
import com.kms.katalon.core.testobject.ResponseObject
import com.kms.katalon.core.util.KeywordUtil
import groovy.json.JsonSlurper

class ApiValidator {

    /**
     * Verifies a nested JSON value using a GPath string
     * @param response The API ResponseObject
     * @param jsonPath The path (e.g., "data.accountDetails[0].balance")
     * @param expectedValue The value you expect to find
     */
    @Keyword
    def verifyNestedValue(ResponseObject response, String jsonPath, Object expectedValue) {
        // Parse the response text into a Groovy object
        def jsonResponse = new JsonSlurper().parseText(response.getResponseText())
        
        // Use Groovy's dynamic GPath to find the value
        def actualValue = jsonPath.split('\\.').inject(jsonResponse) { obj, key -> 
            if (key.contains("[")) {
                def listKey = key.substring(0, key.indexOf("["))
                def index = Integer.parseInt(key.substring(key.indexOf("[") + 1, key.indexOf("]")))
                return obj."$listKey"[index]
            }
            return obj."$key" 
        }

        if (actualValue.toString() == expectedValue.toString()) {
            KeywordUtil.markPassed("Found expected value: " + expectedValue)
        } else {
            KeywordUtil.markFailed("Verification failed! Expected: ${expectedValue} but found: ${actualValue}")
        }
    }
}

```

### **How to use it in your Script:**

Groovy

```auto
def response = WS.sendRequest(findTestObject('Object Repository/API/GetAccount'))

// Use the dot-notation path to verify the 3rd layer of the JSON
CustomKeywords.'ApiValidator.verifyNestedValue'(response, "data.accountDetails[0].balance", 5000.00)

```

> **Architect’s Tip:** If you are unsure of the path, copy your JSON into an online “JSON Path Finder” tool. It will give you the exact string you need to plug into the keyword. Also, remember that JSON arrays (items inside `[]`) are **zero-indexed** , so the first item is always `[0]`.

Do you have a sample of the JSON response? I can help you write the exact path string if the structure is particularly complex!

---

<div class="post-metadata">

**Author:** ![depapp](https://dub1.discourse-cdn.com/katalon/user_avatar/forum.katalon.com/depapp/32/29178_2.png) [@depapp](https://forum.katalon.com/u/depapp)\
**Post date:** [April 25, 2026, 11:44am UTC](https://forum.katalon.com/t/how-do-i-verify-a-value-buried-deep-inside-a-json-response/190370/3 "2026-04-25T11:44:36Z")

</div>

hi @ebauch

maybe you can try to use JsonSlurper into your project

parse the response with JsonSlurper and inspect it in the Variables view to find the exact path.

```groovy
import groovy.json.JsonSlurper

def json = new JsonSlurper().parseText(response.getResponseBodyContent())
def actualBalance = json.data.accountDetails[0].accountBalance

```

for nested arrays, use index brackets like `data.accountDetails[0].accountBalance`. Asserting on the parsed object directly is usually cleaner than WS.verifyElementPropertyValue for complex responses

---

<div class="post-metadata">

**Author:** ![kazurayam](https://dub1.discourse-cdn.com/katalon/user_avatar/forum.katalon.com/kazurayam/32/333_2.png) [@kazurayam](https://forum.katalon.com/u/kazurayam)\
**Post date:** [April 25, 2026, 1:34pm UTC](https://forum.katalon.com/t/how-do-i-verify-a-value-buried-deep-inside-a-json-response/190370/5 "2026-04-25T13:34:17Z")

</div>

> [@ebauch](#):
>
> Is there an easier way to “drill down” into these layers without guessing the path every time?

I will show you a firm way to traverse an object tree derived from a JSON. It works but isn’t fancy like GUI tools.

Create a Test Case, copy & paste the following code:

```auto
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS

import groovy.json.JsonOutput
import groovy.json.JsonSlurper

String json = """
{
  "data": {
	"owner": "I my me mine",
    "address": "somewhere",
    "accountDetails": [
      { "foo": "foo value", "balance": 123 },
      { "bar": "bar value", "balance": 456 },
      { "buz": "buz value", "balance": 789},
      { "type": "Savings", "balance": 5000.00 }
    ]
  }
}
"""

def slurper = new JsonSlurper()
def parsed = slurper.parseText(json)

//def item = parsed
//def item = parsed["data"]
//def item = parsed["data"]["owner"]
//def item = parsed["data"]["accountDetails"]
//def item = parsed["data"]["accountDetails"][0]
//def item = parsed["data"]["accountDetails"][1]
//def item = parsed["data"]["accountDetails"][2]
//def item = parsed["data"]["accountDetails"][3]
//def item = parsed["data"]["accountDetails"][3]["balance"]

String result = JsonOutput.toJson(item)
if (result.startsWith('[') || result.startsWith('{')) {
	println JsonOutput.prettyPrint(result)
} else {
	println result
}

```

You will want to edit this script a little, then run it to see the result.

## parsed[“data”]

Uncoment the line of

```auto
def item = parsed["data"]

```

You run it, then you will see the following output in the Console:

 ![image](https://europe1.discourse-cdn.com/katalon/original/3X/0/1/01a05d23032af0001532391108d4cc1572c0e1a8.jpeg)

## parsed[“data”][“accountDetails”]

You want to comment out the previous line `//def item = parsed["data"]` back. And you want to uncomment another line

```auto
def item = parsed["data"]["accountDetails"]

```

You run it, then you will see the following output in the Console:

```auto
2026-04-25 22:25:43.345 DEBUG testcase.TC1 - 1: println(JsonOutput.prettyPrint(result))
[
    {
        "foo": "foo value",
        "balance": 123
    },
    {
        "bar": "bar value",
        "balance": 456
    },
    {
        "buz": "buz value",
        "balance": 789
    },
    {
        "type": "Savings",
        "balance": 5000.00
    }
]
2026-04-25 22:25:43.372 INFO c.k.katalon.core.main.TestCaseExecutor - END Test Cases/TC1

```

You got a bit closer to the target.

## parsed[“data”][“accountDetails”][0]

You want to comment out the previous line. You want to uncomment another line

```auto
def item = parsed["data"]["accountDetails"][0]

```

You run it, then you will see the following output in the Console:

```auto
2026-04-25 22:28:31.313 DEBUG testcase.TC1 - 1: println(JsonOutput.prettyPrint(result))
{
    "foo": "foo value",
    "balance": 123
}
2026-04-25 22:28:31.339 INFO c.k.katalon.core.main.TestCaseExecutor - END Test Cases/TC1

```

Ah! You missed the target! You want the one in the following sibling.

## parsed[“data”][“accountDetails”][3]

You want to comment out the previous line. You want to uncomment another line:

```auto
def item = parsed["data"]["accountDetails"][3]

```

You run it. Then you will see the following

```auto
2026-04-25 22:31:09.242 DEBUG testcase.TC1 - 1: println(JsonOutput.prettyPrint(result))
{
    "type": "Savings",
    "balance": 5000.00
}
2026-04-25 22:31:09.276 INFO c.k.katalon.core.main.TestCaseExecutor - END Test Cases/TC1

```

Closer, closer.

## parsed[“data”][“accountDetails”][3][“balance”]

You want to comment out the previous line. You want to uncomment another line:

```auto
def item = parsed["data"]["accountDetails"][3]["balance"]

```

You run it. You will see the following result.

```auto
2026-04-25 22:32:07.208 DEBUG testcase.TC1 - 1: println(result)
5000.00
2026-04-25 22:32:07.227 INFO c.k.katalon.core.main.TestCaseExecutor - END Test Cases/TC1

```

You successfully got the number you want.

# Conclusion

See [https://www.baeldung.com/groovy-json](https://www.baeldung.com/groovy-json) for JsonSlurper and JsonOutput.

With certain programming skills, you can move around the target object and eventually come up with a solution.

---

<div class="post-metadata">

**Author:** ![arvind.choudhary](https://dub1.discourse-cdn.com/katalon/user_avatar/forum.katalon.com/arvind.choudhary/32/33165_2.png) [@arvind.choudhary](https://forum.katalon.com/u/arvind.choudhary)\
**Post date:** [April 25, 2026, 3:20pm UTC](https://forum.katalon.com/t/how-do-i-verify-a-value-buried-deep-inside-a-json-response/190370/6 "2026-04-25T15:20:35Z")

</div>

This usually happens because the API response is **nested and contains arrays** , and `WS.verifyElementPropertyValue()` requires an **exact JSON path** (including array indexes). If the path is slightly wrong, Katalon returns `null`.

Best way would be to parse the response using Groovy instead of guessing paths:  
import groovy.json.JsonSlurper

def json = new JsonSlurper().parseText(response.getResponseBodyContent())

def balance = json.data.accountDetails[0].accountBalance

assert balance == 5000
