Search code examples
javajsonrest-assuredrest-assured-jsonpath

Is there a way to find a JSON response element value based on another element value?


Using the below method i could get the "id" element(first element in first list) value. i need to get that element value but based on the condition of another element "gifts.nameEn"

Response response = request.post("/pop/transaction/inquiry");
JsonPath jsonPathEvaluator = response.jsonPath();

List<HashMap> activeCampaignsList = jsonPathEvaluator.getList("");
for(int i=0; i< activeCampaignsList.size(); i++)
{
        offerId = activeCampaignsList.get(i).get("id").toString();
        break;
}

And Here's the response snippet so you would be aware of what exactly i'm looking for:

[ { "**id**": 1222, "type": "WITHIN_TRANSACTION", "gifts": [ { "startDate": "2019-06-26", "endDate": "2019-06-26", "id": 26130, "nameAr": "abcd201957261140057", "nameEn": "*abcd201957261140057*",

Solution

  • RestAssured allows you use JsonPath which has a strong utility in JSON processing. Instead of working with paths, you can convert JSON to Java Objects and I will show you exactly how to do it.

    So, your JSON starts with an array of elements. Each of the element is JSON Object. Each of the JSON Object contains nested JSON Array gifts with JSON Objects in it. Let me explain further.

    We have to process the array first, the start of your JSON [. In order to do that we can create a class representing this Array like this:

    public class ElementObject { //this name is irrelevant. You can call it whatever you want
        public String id; //the names of the variables are relevant
        public String type; //each of variable name corresponds to the type and name in the JSON
        public List<GiftObject> gifts; //here we handle the nested JSON Array of JSON Objects
    }
    

    Now, we require an object to handle gifts. That will require another class:

    public class GiftObject { //irrelevant name
        public String startDate; //relevant name
        public String endDate;
        public String id;
        public String nameAr;
        public String nameEn;
    }
    

    Now, all we have to do is call 1 method from JsonPath to parse whole JSON into Java classes. Like this:

    response.jsonPath().getObject("", ElementObject[].class);
    

    That's mostly it. Starting from the top:

    [  
       {  
          "id":1222,
          "type":"WITHIN_TRANSACTION",
    

    We have an JSON Array with JSON Objects. 1 JSON Object equals 1 instance of ElementObject class. All of the objects from the Array will be parsed into ElementObject[].class and JsonPath will create an instance using Java Reflection (You don't have to worry about that).

    "gifts": [ { "startDate": "2019-06-26", "endDate": "2019-06-26", "id": 26130, "nameAr": "abcd201957261140057", "nameEn": "abcd201957261140057",
    

    Each of the gifts will be parsed into new instance of GiftObject and storred in List<GiftObject> in ElementObject class.

    All we have to do now is work on our Java classes.

    To fully answer your question - you need ID value based on gifts.nameEn

    for (ElementObject element : elements) {
                for (GiftObject gift : element.gifts) {
                    if (gift.nameEn.equals("abcd201957261140057")) {
                        System.out.println(element.id);
                    }
                }
            }
    

    The above for loop can be easily replaced with a method, or Java Streams. Whatever suits you the most.

    Given the above code the results will be:

    1222
    

    Hope it helps!

    EDIT: If you get the Exception like this Cannot deserialize object because of no JSON deserializer found in classpath. Please put either Jackson (Databind) or Gson in the classpath. all you have to do is add jackson-databind to Maven. Rest Assured is able to use Gson or Jackson databind to transform JSON into Java classes. All you need is the dependency, and you are all set.

            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.9.9</version>
            </dependency>