How has KarateDSL simplified JsonPath evaluation?

Priyanka Brahmane
7 min readMay 17, 2021

--

Welcome back, TestCommunity!!!

First and foremost, I’d like to ask you all “how you’re doing and how things are going at your end ?”

I hope you’re enjoying my Karate DSL blog series, which aims to cover all the key features offered by this fabulous tool. Today we’ll look at methods for extracting json objects/values from complex payloads.

Let’s start with the fundamentals of JSONPath before moving on to advanced concepts.

What is JSONPath ?

JSONPath is a query language for JSON which is used for selecting and extracting a JSON document’s property values.

The following JSONPath syntax rules should be followed in order to extract desired JSON objects:

  • The root object or element is denoted by the “$” symbol.
  • The “.” dot operator is used to denote a child element of the current element.
  • The “..” operator is used for deep scan any elements by name in entire JSON payload
  • The “@” symbol corresponds to the current entity or element.
  • The subscript operator “[ ]” is used to indicate a child element of the currently selected element (by name or index).
  • The “*” operator returns all objects when used as a wildcard.
  • “[? (<expression> )]” to get a list of all items that match a set of criteria by returning boolean value.

For more details on JSONPath refer this link.

JSONPath Implementation in KarateDSL

Karate allows you to elegantly extract the desired object’s JsonPath from a complex API response, let us see how can we achieve this ?

We have to first download latest maven dependency for JsonPath: https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path

<!-- https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path -->
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.5.0</version>
</dependency>

Jayway has it own JsonPath evaluator, we may use this to ensure that the json paths are accurate.

Stated API is used in all of the examples below-http://openlibrary.org/api/volumes/brief/isbn/9780525440987.json

Response:

{
"records": {
"/books/OL2842220M": {
"isbns": [
"0525440984",
"9780525440987"
],
"issns": [],
"lccns": [
"84004132"
],
"oclcs": [
"10557711"
],
"olids": [
"OL2842220M"
],
"publishDates": [
"1984"
],
"recordURL": "http://openlibrary.org/books/OL2842220M/Interstellar_pig",
"data": {
"url": "http://openlibrary.org/books/OL2842220M/Interstellar_pig",
"key": "/books/OL2842220M",
"title": "Interstellar pig",
"authors": [
{
"url": "http://openlibrary.org/authors/OL19688A/William_Sleator",
"name": "William Sleator"
}
],
"number_of_pages": 197,
"pagination": "197 p. ;",
"by_statement": "William Sleator.",
"identifiers": {
"librarything": [
"52348"
],
"goodreads": [
"3891166"
],
"isbn_10": [
"0525440984"
],
"isbn_13": [
"9780525440987"
],
"lccn": [
"84004132"
],
"oclc": [
"10557711"
],
"openlibrary": [
"OL2842220M"
]
},
"classifications": {
"lc_classifications": [
"PZ7.S6313 Ik 1984"
],
"dewey_decimal_class": [
"[Fic]"
]
},
"publishers": [
{
"name": "E.P. Dutton"
}
],
"publish_places": [
{
"name": "New York, N.Y"
}
],
"publish_date": "1984",
"subjects": [
{
"name": "Juvenile fiction",
"url": "https://openlibrary.org/subjects/juvenile_fiction"
},
{
"name": "Science fiction",
"url": "https://openlibrary.org/subjects/science_fiction"
},
{
"name": "Human-alien encounters",
"url": "https://openlibrary.org/subjects/human-alien_encounters"
},
{
"name": "Games",
"url": "https://openlibrary.org/subjects/games"
},
{
"name": "Swine",
"url": "https://openlibrary.org/subjects/swine"
},
{
"name": "Vacations",
"url": "https://openlibrary.org/subjects/vacations"
},
{
"name": "Juvenile literature",
"url": "https://openlibrary.org/subjects/juvenile_literature"
},
{
"name": "Reading Level-Grade 7",
"url": "https://openlibrary.org/subjects/reading_level-grade_7"
},
{
"name": "Reading Level-Grade 6",
"url": "https://openlibrary.org/subjects/reading_level-grade_6"
},
{
"name": "Reading Level-Grade 9",
"url": "https://openlibrary.org/subjects/reading_level-grade_9"
},
{
"name": "Reading Level-Grade 8",
"url": "https://openlibrary.org/subjects/reading_level-grade_8"
}
],
"notes": "Sequel: Parasite Pig.\n\nAccelerated Reader/Renaissance Learning UG 5.6 8.\n",
"ebooks": [
{
"preview_url": "https://archive.org/details/interstellarpig00slea",
"availability": "borrow",
"formats": {},
"borrow_url": "https://openlibrary.org/books/OL2842220M/Interstellar_pig/borrow",
"checkedout": false
}
],
"cover": {
"small": "https://covers.openlibrary.org/b/id/360801-S.jpg",
"medium": "https://covers.openlibrary.org/b/id/360801-M.jpg",
"large": "https://covers.openlibrary.org/b/id/360801-L.jpg"
}
},
"details": {
"bib_key": "isbn:9780525440987",
"info_url": "http://openlibrary.org/books/OL2842220M/Interstellar_pig",
"preview": "borrow",
"preview_url": "https://archive.org/details/interstellarpig00slea",
"thumbnail_url": "https://covers.openlibrary.org/b/id/360801-S.jpg",
"details": {
"publishers": [
"E.P. Dutton"
],
"number_of_pages": 197,
"ia_box_id": [
"IA132417"
],
"links": [
{
"url": "http://www.angelfire.com/mi/willsleator/"
}
],
"isbn_10": [
"0525440984"
],
"covers": [
360801,
6801034
],
"full_title": "Interstellar pig",
"lc_classifications": [
"PZ7.S6313 Ik 1984"
],
"latest_revision": 10,
"key": "/books/OL2842220M",
"authors": [
{
"key": "/authors/OL19688A",
"name": "William Sleator"
}
],
"ocaid": "interstellarpig00slea",
"publish_places": [
"New York, N.Y"
],
"description": {
"type": "/type/text",
"value": "Barney's boring seaside vacation suddenly becomes more interesting when the cottage next door is occupied by three exotic neighbors who are addicted to a game they call \"Interstellar Pig.\""
},
"languages": [
{
"key": "/languages/eng"
}
],
"pagination": "197 p. ;",
"source_records": [
"marc:marc_records_scriblio_net/part17.dat:49385436:792",
"ia:interstellarpig00slea",
"marc:marc_loc_2016/BooksAll.2016.part15.utf8:118693297:792"
],
"title": "Interstellar pig",
"dewey_decimal_class": [
"[Fic]"
],
"notes": {
"type": "/type/text",
"value": "Sequel: Parasite Pig.\n\nAccelerated Reader/Renaissance Learning UG 5.6 8.\n"
},
"identifiers": {
"librarything": [
"52348"
],
"goodreads": [
"3891166"
]
},
"isbn_13": [
"9780525440987"
],
"created": {
"type": "/type/datetime",
"value": "2008-04-01T03:28:50.625462"
},
"edition_name": "1st ed.",
"lccn": [
"84004132"
],
"publish_date": "1984",
"publish_country": "nyu",
"last_modified": {
"type": "/type/datetime",
"value": "2020-10-30T16:16:40.871402"
},
"by_statement": "William Sleator.",
"oclc_numbers": [
"10557711"
],
"works": [
{
"key": "/works/OL55607W"
}
],
"type": {
"key": "/type/edition"
},
"revision": 10
}
}
}
},
"items": []
}

For more open-source APIs click on this link.

Example 1: Get an objects present in “ebook” array.

And def data = $..ebooks[*]And print data

Example 2: Get “lccn” key on the 0th index of “identifiers” array.

Example 3: Get all the “name” keys from “subjects” error excluding “url”.

# Get subjects arrayAnd def subjects = $..subjects# From subjects array get all namesAnd def subject_name = karate.jsonPath(subjects,"$..['name']")And print subject_name

Please note: In karate, you can retrieve a few keys (rather than the entire object) from a JSON array or an object, this can be achieved by using square brackets along with comma(,) separated key names in karate.jsonPath method.

karate.jsonPath(response, "$..['key1','key2','key3']")

Example 4: Obtain all subjects with the word “Grade” in their names.

We are using regex to match characters.

And def subject_name_grade = karate.jsonPath(response, "$..subjects[?(@.name =~ /.*Grade.*/i)]")

Example 5: Get subject url present on the last index and subject names on the last to index of the array

And def last_subject_url = karate.jsonPath(response, "$..subjects[-1:].url" )
And print last_subject_url
And def second_subject_name = karate.jsonPath(response, "$..subjects[-2:].name" )
And print second_subject_name

Example 6 : Get JSON object based on indexes range.

We can use StartIndex : DesiredEndIndex which mean start from index 1 (inclusive) until index 2 (exclusive)

# Get first 3 object from JSON arrayAnd def subjects = karate.jsonPath(response, "$..subjects" )[0]And def First_three_subjects = karate.jsonPath(subjects, "$..[0:3]")And print karate.sizeOf(First_three_subjects)And print First_three_subjects

Example 7: Get size of the array by using karate.jsonPath method

Method 1: The traditional method of obtaining the size is to extract the array into a single variable and then transfer it to karate.sizeOf() is a method.

And def subjects = karate.jsonPath(response, "$..subjects[*]" )And print subjectsAnd def subject_length_via_karate = karate.sizeOf(subjects)And print subject_length_via_karate

Method 2: We can also shorten the line of codes by passing karate.jsonPath() method inside karate.sizeOf() method, it will give you the same result:

And def subject_length_via_karate = karate.sizeOf(karate.jsonPath(response, "$..subjects[*]" ))And print subject_length_via_karate

Example 8: There are times when dynamically obtaining values from a JSON response is needed. We’ll see how to get the value of the “url” key by passing the subject name in the example below.

Method 1: To get relevant objects, you can transfer a hardcoded value into a variable and use in the jsonPath method.

And def name = 'Vacations'And def get_vacation_url = karate.jsonPath(response, "$..[?(@.name=='" + name + "')].url" )And print get_vacation_url

Method 2: By following the steps below, you can make it absolutely dynamic:

And def book_name = $..subjects[5].nameAnd def get_vacation_url1 = karate.jsonPath(response, "$..[?(@.name=='" + book_name + "')].url" )And print get_vacation_url1

Note: If you do not pass “.url” in the jsonPath it will return entire JSON object which matches passed variable condition.

Example 9: Get the JSON objects excluding an object based on a condition.

Below example shows steps to get all JSON objects from subjects array excluding name that matches ‘Juvenile fiction’.

And def subjects = karate.jsonPath(response, "$..subjects" )[0]And def First_three_subjects = karate.jsonPath(subjects, "$..[0:2]" )And print karate.sizeOf(First_three_subjects)And print First_three_subjectsAnd def condition = function(x) { return x.name != "Juvenile fiction"; }And def data_after_filteration = karate.filter(First_three_subjects, condition)And print karate.sizeOf(data_after_filteration)And print data_after_filteration

I’ll end this blog now, hoping that it has helped you understand the numerous methods for extracting desired objects from even the most complex JSON responses returned by APIs. In the next blog, we’ll look at different forms of assertions and matches.

Please share your thoughts in the comments section below and click the Follow button if you find this blog useful. I hope to see you again in the upcoming posts. You may also connect with me on LinkedIn.

Until then, stay safe and strong; we’ll make it through this!!

Happy Learning!!!

--

--

Priyanka Brahmane
Priyanka Brahmane

Written by Priyanka Brahmane

AM SDET Automation @M&G | QA Lead @ MyGlamm | QA Automation engineer @ Ex-Paytm Insider| Ex-Automation Tester @ Reliance Jio Infocomm Ltd. | Ex-Software Develop