REST Assured: Fetch JSON using JayWay's JsonPath

Profile picture for user arilio666
  • So here in this article, we will look at another JSON path implementation called the jay way JSON path.
  • This is different from the previous article we saw, which is solely on groovy gpath implementation.
  • Unlike gpath, this one is not directly workable with rest assured as we need to add this below dependency in maven repo.
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.6.0</version>
</dependency>
  • The expression in JSON path is different from gpath in that it solely refers to the JSON structure in the same way of XPath.
  • The root member object in the JSON path is referred to as $ regardless of whether it is an array or an object.
  • It is pretty popular with java and widely used and expressed in dot notation navigation.
$.head.name[0].age

Or it can be notated in brackets too.

$[head][name][0][age]

Groovy used gpath expressions in the syntax, but here JSON path uses operators.

$- Starts the expression 
@- Current node processed by filter predicate.
*- Wildcard
..- Deep scan whenever a name is required. 
.<name>-   Dot-notated child
['<name>' (, '<name>')]- Bracket-notated child or children
[<number> (, <number>)]- Array index or indexes
[start:end]- Array slice operator
[?(<expression>)]- Filter expression. The expression must evaluate a boolean value.

JSON path can also use functions at the tail end of a path.

Min ()- Provides minimum value in an array.
Max ()- Provides maximum value in an array.
Avg ()- Provides average value in an array.
stddev()- Provides standard deviation value in an array.
Length ()- Provides the size of a value in an array.
Sum ()- Provides sum of a value in an array.
Keys ()- Provides property keys.
Concat (X)- Provides the concatenated version of the path output.
append(X)- add an item to the JSON path output array

We also have filters that use logical expressions to filter out the necessary information from a JSON body.

== left is equal to right.
!= left is not equal to right
< Less than
<=    Less than or equals
>    Greater than
>=    greater than or equals
=~    left matches regular expression [?(@.name =~ /foo.*?/i)]
in    left exists in right [?(@.size in ['S', 'M'])]
nin    left does not exists in right
subsetof    left is a subset of right [?(@.sizes subsetof ['S', 'M', 'L'])]
anyof    left has an intersection with right [?(@.sizes anyof ['M', 'L'])]
noneof    left has no intersection with right [?(@.sizes noneof ['M', 'L'])]
size    size of left (array or string) should match right
empty    left (array or string) should be empty

Enough talk. Let us dive into the concept in the real-time scenario and parse the JSON body using a JSON path.

We are going to use this JSON for example purpose:

{
    "store": {
        "rice": [
            {
                "category": "brown rice",
                "brand": "oro brown rice",
                "price": 8.95
            },
            {
                "category": "red rice",
                "brand": "blured red rice",
                "price": 12.99
            },
            {
                "category": "white rice",
                "brand": "lilly white rice",
                "price": 8.99
            }
        ],
        "milk": {
            "color": "blue",
            "price": 19.95
        }
    },
    "expensive": 30
}

I want to fetch the details of rice alone:

$.store.rice

Result:

[
  [
    {
      "category": "brown rice",
      "brand": "oro brown rice",
      "price": 8.95
    },
    {
      "category": "red rice",
      "brand": "blured red rice",
      "price": 12.99
    },
    {
      "category": "white rice",
      "brand": "lilly white rice",
      "price": 8.99
    }
  ]
]

I want brown rice and white rice details alone:

$.store.rice[0,2]

Result:

[
  {
    "category": "brown rice",
    "brand": "oro brown rice",
    "price": 8.95
  },
  {
    "category": "white rice",
    "brand": "lilly white rice",
    "price": 8.99
  }
]

I want brand names of all rice:

$.store.rice[*].brand

Result:

[
  "oro brown rice,"
  "blurred red rice,"
  "lilly white rice"
]

I want all categories:

$..category

Result:

[
  "brown rice",
  "red rice",
  "white rice"
]

I want to see all the details inside this present JSON body:

$.store.*

Result:

[
  [
    {
      "category": "brown rice",
      "brand": "oro brown rice",
      "price": 8.95
    },
    {
      "category": "red rice",
      "brand": "blured red rice",
      "price": 12.99
    },
    {
      "category": "white rice",
      "brand": "lilly white rice",
      "price": 8.99
    }
  ],
  {
    "color": "blue",
    "price": 19.95
  }
]

I want all rice details from index 0 to 1 exclusive of 2:

$..rice[:2]

Result:

[
  {
    "category": "brown rice",
    "brand": "oro brown rice",
    "price": 8.95
  },
  {
    "category": "red rice",
    "brand": "blured red rice",
    "price": 12.99
  }
]

I want all rice price in store which is less than 10:

$.store.rice[?(@.price < 10)]

Result:

[
  {
    "category": "brown rice",
    "brand": "oro brown rice",
    "price": 8.95
  },
  {
    "category": "white rice",
    "brand": "lilly white rice",
    "price": 8.99
  }
]

These are ways we can use the JSON path to parse JSON body structure and filter out pieces of information using jay way JSON path operators, functions, and filters.
Try out these expressions through www.jsonpath.com.