javajsonrest-assuredrest-assured-jsonpathgpath

How to get the summation of values using gpath sum() in restassured on JSON Object


I was trying to find the summation of deceased count from JSON object extract from the following JSON response

https://api.covid19india.org/state_district_wise.json

Snippet from above is json

"Maharashtra": {
    "districtData": {
      "Ahmednagar": {
        "notes": "",
        "active": 4206,
        "confirmed": 275516,
        "migratedother": 1,
        "deceased": 5565,
        "recovered": 265744,
        "delta": {
          "confirmed": 559,
          "deceased": 4,
          "recovered": 0
        }
      },

I want to find the sum of the deceased from the state of Maharashtra. I know we can use collect on JSONArray but here is JSONObject. I tried following but to no avail

int value=jsonPath.get("Maharashtra.districtData.collect{it.deceased}.sum()");

Solution

  • There are 2 deceased keys in the object, I assume that you only want the deceased in the outer object. The simplest solution I get so far.

    @Test
    void name3() {
        Response res = RestAssured.given()
                .get("https://api.covid19india.org/state_district_wise.json");
        Map<String, ?> data = res.jsonPath().getMap("Maharashtra.districtData");
        Set<String> keys = data.keySet();
        int sum = keys.stream()
                .mapToInt(key ->
                   JsonPath.read(res.asString(), String.format("$.Maharashtra.districtData.[\"%s\"].deceased", key)))
                .sum();
        System.out.println(sum); //126851
    }
    

    In case, you don't want to use Java8 stream.

    int sum = 0;
    for (String key : keys) {
        int deceased = JsonPath.read(res.asString(), String.format("$.Maharashtra.districtData.[\"%s\"].deceased", key));
        sum += deceased;
    }
    

    I use JsonPath (com.jayway.jsonpath.JsonPath)

    pom.xml

    <dependency>
        <groupId>com.jayway.jsonpath</groupId>
        <artifactId>json-path</artifactId>
        <version>2.6.0</version>
    </dependency>
    

    Update

    I come up with another solution, that using mapping POJO.

    @Test
    void name4() {
        Response res = RestAssured.given()
                .get("https://api.covid19india.org/state_district_wise.json");
    
        Configuration configuration = Configuration.builder()
                .jsonProvider(new JacksonJsonProvider())
                .mappingProvider(new JacksonMappingProvider())
                .build();
    
        List<DistrictData> data = JsonPath.using(configuration).parse(res.asString())
                .read("$.Maharashtra.districtData.*", new TypeRef<>() {});
    
        int sum = data.stream().mapToInt(DistrictData::getDeceased).sum();
        System.out.println(sum); //126851
    }
    

    POJO

    import lombok.Data;
    import java.util.Map;
    
    @Data
    public class DistrictData {
        private String notes;
        private int active;
        private int confirmed;
        private int migratedother;
        private int deceased;
        private int recovered;
        private Map<String, Object> delta;
    }