Search code examples
rest-assuredrest-assured-jsonpath

Accessing jsonpath elements with nested objects


I am looking to extract certain values from a JSON path of arrays and objects and use these values for further processing and am struggling with accessing those elements. Here is the JSON response:

[  
 {  
  "od_pair":"7015400:8727100",
  "buckets":[  
     {  
        "bucket":"C00",
        "original":2,
        "available":2
     },
     {  
        "bucket":"A01",
        "original":76,
        "available":0
     },
     {  
        "bucket":"B01",
        "original":672,
        "available":480
     }
    ]
    },
 {  
  "od_pair":"7015400:8814001",
  "buckets":[  
     {  
        "bucket":"C00",
        "original":2,
        "available":2
     },
     {  
        "bucket":"A01",
        "original":40,
        "available":40
     },
     {  
        "bucket":"B01",
        "original":672,
        "available":672
     },
     {  
        "bucket":"B03",
        "original":632,
        "available":632
     },
     {  
        "bucket":"B05",
        "original":558,
        "available":558
     }
    ]
 }
]

I tried accessing the root elements with $ but I could not get further with it.

Here is the test method that I have written. I want to extract the value for od_pair and within each od_pair, I need to be able to retrieve the bucket codes and their available numbers.

public static void updateBuckets(String ServiceName, String DateOfJourney) throws Exception {
    File jsonExample = new File(System.getProperty("user.dir"), "\\LogAvResponse\\LogAvResponse.json");
    JsonPath jsonPath = new JsonPath(jsonExample);

    List<Object> LegList = jsonPath.getList("$");
    // List<HashMap<String, String>> jsonObjectsInArray = jsonPath.getList("$");

    int NoofLegs = LegList.size();
    System.out.println("No of legs :" + NoofLegs);
    for (int j = 0; j <= NoofLegs; j++)
    // for (HashMap<String, String> jsonObject : jsonObjectsInArray) {
    {

        String OD_Pair = jsonPath.param("j", j).getString("[j].od_pair");
        // String OD_Pair = jsonObject.get("od_pair");

        System.out.println("OD Pair: " + OD_Pair);
        List<Object> BucketsList = jsonPath.param("j", j).getList("[j].buckets");

        int NoOfBuckets = BucketsList.size();
        // System.out.println("OD Pair: " + OD_Pair);
        System.out.println("no of Buckets: " + NoOfBuckets);

        for (int i = 0; i < NoOfBuckets; i++) {
            String BucketCode = jsonPath.param("j", j).param("i", i).getString("[j].buckets[i].bucket");
            String Available = jsonPath.param("j", j).param("i", i).getString("[j].buckets[i].available");

            int BucketCodeColumn = XLUtils.getBucketCodeColumn(BucketCode);
            int ServiceRow = XLUtils.getServiceRow(ServiceName, DateOfJourney, OD_Pair);
            System.out.println("Row of " + ServiceName + ":" + DateOfJourney + "is:" + ServiceRow);
            System.out.println("Bucket Code column of " + BucketCode + " is: " + BucketCodeColumn);
            XLUtils.updateAvailability(ServiceRow, BucketCodeColumn, Available);
        }
    }

}

}

This is the error I see:

Caused by: 
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup 
failed:
Script1.groovy: 1: unexpected token: [ @ line 1, column 27.
restAssuredJsonRootObject.[j].od_pair

Can someone help me please?


Solution

  • I would suggest parsing your JSON into Java classes to ease the processing.

    How to do that? First, we need to create Java classes which will represent the JSON you provided.

    Let's analyze the JSON. Starts with an array. The array contains multiple JSON Object. These objects contain od_pair value and array of objects called buckets.

    Let's create a class (you can name it whatever you want) Pair

    public class Pair {
        public String od_pair; //this name is important because it corresponds with the json element's name!
        public List<BucketObject> buckets; //same here!
    }
    

    This class represents a single JSON Object in the main Array. It contains od_pair value AND nested JSON Array but in Java representation -> List of BucketObject classes. Let's create BucketObject class:

    public class BucketObject { //this name is NOT importnat
        public String bucket; //names are important
        public int original;
        public int available;
    }
    

    We have only 3 values in each of the objects.

    Now, it's time to parse JSON into the written classes.

    JsonPath path = JsonPath.from(json);
    Pair[] pairs = path.getObject("$", Pair[].class);
    

    Remember that Pair is a single JSON Object. That's why we start parsing from the root represented by dollar sign $ and we declare that JSON should be parsed into an ARRAY of Pair objects!

    Now, processing will be much simpler!

    I am not sure what do you need, but I will show you an example of how to get data from the buckets based on od_pair field and you should be able to figure out the rest of the processing.

    So, we have the array of Pair class: Pair[] pairs;

    Now, we want to get 1 Pair object based on od_pair value.

        public static Pair getPairBasedOnOdPairValue(Pair[] pairs, String odPairValue) {
            for (Pair pair : pairs) {
                if (pair.od_pair.equals(odPairValue)) return pair;
            }
    
            throw new NoSuchElementException();
        }
    

    Now, we have the Pair object. We can access buckets for this object using

    List<BucketObject> buckets = pair.buckets;
    

    The rest of the processing is iterating over List<BucketObject> and getting desired values.

    Hope it helps!