REST-Assured - JsonPath for fetching a list of values
Asked Answered
O

2

8

I'm using REST-Assured for testing some RESTful webservices. Here's my JSON:

{
    "status":true,
    "responseData":{
        "orderLevelReasons":[
            {
                "reasons":[
                    {
                        "reasonId":"129cfea8-b022-4dc8-9811-222a324f46aa",
                        "reasonName":"COD Amount Mismatch"
                    },
                    {
                        "reasonId":"a881fd5c-626e-438c-8026-646aa2a19098",
                        "reasonName":"Gave wrong information"
                    },
                    {
                        "reasonId":"543d438a-88cc-487c-86e4-19eecefa9ca7",
                        "reasonName":"Late delivery"
                    },
                    {
                        "reasonId":"080cd7c1-7a37-48ad-9090-57286d93ea41",
                        "reasonName":"Parcel not received"
                    },
                    {
                        "reasonId":"5ca3d9b4-0fa2-49da-a534-a6f2e7eccc07",
                        "reasonName":"Staff did not inform about the parcel arrival"
                    }
                ],
                "issueName":"ISSUE TYPE 1",
                "issueId":"0c2c37a6-62b6-4c28-ab6c-566487d045bd",
                "hint":""
            },
            {
                "reasons":[
                    {
                        "reasonId":"129cfea8-b022-4dc8-9811-222a324f46aa",
                        "reasonName":"COD Amount Mismatch"
                    },
                    {
                        "reasonId":"14975b5d-23fb-4735-8082-2e02d6335788",
                        "reasonName":"Data issue"
                    },
                    {
                        "reasonId":"7e6e8446-3774-4589-9171-8e7ab0a7f73b",
                        "reasonName":"Delivery BOY did not inform before delivering"
                    },
                    {
                        "reasonId":"543d438a-88cc-487c-86e4-19eecefa9ca7",
                        "reasonName":"Late delivery"
                    },
                    {
                        "reasonId":"080cd7c1-7a37-48ad-9090-57286d93ea41",
                        "reasonName":"Parcel not received"
                    },
                    {
                        "reasonId":"8e430c71-f28b-49e4-9946-e0bd5131768b",
                        "reasonName":"Refuse to come doorstep"
                    },
                    {
                        "reasonId":"515d0fa4-a44c-47eb-a7a2-5ddae778f37a",
                        "reasonName":"Extra Amount taken By Partner Staff"
                    }
                ],
                "issueName":"ISSUE TYPE 2",
                "issueId":"ac902377-3db2-462a-8e53-48b06d1aff1f",
                "hint":""
            }
        ],
        "productLevelReasons":[
            {
                "reasons":[
                    {
                        "reasonId":"6129dcb8-1ae5-4d7d-9c95-4c0ec2f69ded",
                        "reasonName":"Some reason1"
                    },
                    {
                        "reasonId":"febec32b-b243-4509-b46a-20d9f4747ca3",
                        "reasonName":"Some reason2"
                    },
                    {
                        "reasonId":"d8a492b8-f816-41e6-b45d-5ec29f3a0785",
                        "reasonName":"Some reason3"
                    },
                    {
                        "reasonId":"c0c98489-6401-455a-9145-f52664d8aff4",
                        "reasonName":"Some reason4"
                    },
                    {
                        "reasonId":"ef2b4147-ee76-4961-b784-63e848a84167",
                        "reasonName":"Some reason5"
                    },
                    {
                        "reasonId":"7f4f9657-17b2-407b-aed7-16b221bf3229",
                        "reasonName":"Some reason6"
                    },
                    {
                        "reasonId":"2aa83be6-60cb-43dc-9273-c41e6047315e",
                        "reasonName":"Others"
                    },
                    {
                        "reasonId":"c432f563-f835-4710-8055-5ee9e0fe1409",
                        "reasonName":"Some reason7"
                    }
                ],
                "orderItemName":"Item1",
                "orderItemId":961253,
                "hint":""
            }
        ]
    },
    "message":"OK"
}

I would like to fetch:

  1. A list of all reasonId values under responseData.orderLevelReasons.
  2. A list of all reasonId values under responseData.productLevelReasons where orderItemId is 961253 (as there could be productLevelReasons for multiple orderItemIds).

I Googled for this quite a lot and found that this can be achieved using JsonPath, but I could not figure out what exactly would be the JsonPath expressions for each of my purposes.

Ourself answered 12/4, 2017 at 9:4 Comment(0)
L
8

A list of all reasonId values under responseData.orderLevelReasons

$.responseData.orderLevelReasons[*].reasons[*].reasonId

The [*] for orderLevelReasons is necessary if you want the reasons from all items in the orderLevelReasons collection. If not you can replace it with [0] and you can get a distinct list (assuming the same reasons repeat for each orderLevelReasons).

A list of all reasonId values under responseData.productLevelReasons where orderItemId is 961253 (as there could be productLevelReasons for multiple orderItemIds).

$.responseData.productLevelReasons[?(@.orderItemId=='961253')].reasons[*].reasonId

This is also not distinct. You'll need to de-duplicate if duplicate reasons can exist.

I validated both of your JsonPath expressions at jsonpath.curiousconcept.com, both of them are valid. But the Java code gives error for some reason.

I have looked into this. The rest-assured framework does not actually implement JsonPath, but a proprietary path based query syntax for JSON. Unhappily the name is the same but it is actually based on a completely different standard.

This docs page explains:

Note that the JsonPath implementation uses Groovy's GPath syntax and is not to be confused with Jayway's JsonPath implementation.

The JsonPath tag on StackOverflow is concerned with the accepted JsonPath specification, and not the rest-assured specification.

Based on my research I would conclude that the rest-assured jsonpath implementation does not support your requirement. You should use an implementation that does, such as Jayway's one.

Loppy answered 12/4, 2017 at 9:47 Comment(5)
Thanks Tom! I'm trying to use the JsonPath expression in this way: List<String> orderLevelReasons = new ArrayList<String>(); orderLevelReasons = jsonPath.getList("$.responseData.orderLevelReasons[*].reasons[*].reasonId"); but that gives an error Invalid JSON expression.Ourself
I validated both of your JsonPath expressions at jsonpath.curiousconcept.com, both of them are valid and return expected outputs. But the Java code gives error for some reason. :(Ourself
Thanks Tom! I realised that I was trying with REST-Assured's JsonPath, but with Jayway's JsonPath your second expression gives valid output from my code, but the first expression returns an empty list.Ourself
I was trying with List<Object>. After trying with List<String>, it is working as expected. Thanks a ton Tom! I'd like to know how you derived the JsonPath expressions though. :)Ourself
@AkshayMaldhure - I read the spec ;). The string equality thing I just found by accident playing around. It makes sense that this should work like javascript string equality.Loppy
O
0

In case you don't want to use groovy path you can use JsonPath.getList("path") to fetch the data.

JsonPath.getList("responseData.orderLevelReasons.reasons.reasonId");

enter image description here

enter image description here

Oneupmanship answered 18/3 at 13:14 Comment(2)
add valid names for image urlsSewell
Why should I not upload images of code/data/errors? I also think you should learn how to use markdown. By the way - and pardon my ignorance - what is "groovy path" ?Truman

© 2022 - 2024 — McMap. All rights reserved.