0

I am trying to count the values a json array.

I want to count the number of id's in the data array of "sierra" if "beta = b". Hence checking the value of data[].beta against the environment variable ("B") set to value 'b'.

The issue here is I do not have "sierra" in every iteration of data[].

{
  "data": [{
        "alpha": "a",
        "beta": "b",
        "delta": {
            "cat": "dog"
        },
        "gamma": {
            "sierra": {
                "data": [
                    {
                        "type": "alphabet",
                        "id": "a"
                    },
                    {
                        "type": "alphabet",
                        "id": "b"
                    }
                ]
            }
        }
   },
{
        "alpha": "a",
        "beta": "b",
        "delta": {
            "cat": "dog"
        },
        "bravo": {
                "data": [
                    {
                        "type": "number",
                        "id": "1"
                    },
                    {
                        "type": "number",
                        "id": "2"
                    }
                ]
            }
        }
   },
{
        "alpha": "x",
        "beta": "y",
        "delta": {
            "cat": "dog"
        },
        "gamma": {
            "sierra": {
                "data": [
                    {
                        "type": "alphabet",
                        "id": "c"
                    },
                    {
                        "type": "alphabet",
                        "id": "d"
                    }
                ]
            }
        }
   }]
}

Above json is the response body I see in postman. "loop" is the count of my "for" loop.

EDIT 1: I've tried this:

1. pm.response.json().data[loop].gamma.sierra.data().id).size()

2. for(var loop =0; loop < pm.response.json().data.length; loop++)
{
 if(pm.response.json().data[loop].beta===pm.variables.get("B"))
{      
        pm.response.json().data.map((item, loop) => {
            if(item.gamma){ // check if gamma key is present
                console.log(item.gamma.sierra.filter(data =>data.id 
                                                      ).length); // 
            }
        });
        result=true;
        break;

    }
}
pm.expect(true).to.eql(result);

Expected: 2

Actual: TypeError: Cannot read property 'sierra' of undefined
Actual: item.relationships.apps.filter is not a function
Siva
  • 113
  • 1
  • 16
  • 1
    What is `loop` in your code ? – Mihai Alexandru-Ionut Jun 27 '19 at 06:45
  • You can find it by pm.response.json().data[loop].gamma.sierra.data().length – Saniya syed qureshi Jun 27 '19 at 06:45
  • Try logging in `pm.response.json().data[loop]` first. It appears that one or few of the `data[loop]` is missing the `gamma` key. – Nuhman Jun 27 '19 at 06:46
  • @MihaiAlexandru-Ionut I guess he is running a loop and `loop` is the index number. – Nuhman Jun 27 '19 at 06:47
  • You attempt to call a function that does not exist: .sierra.data(). In your casa data is just an array. – Amiga500 Jun 27 '19 at 06:49
  • @Nuhman Yes. I do not have the "gamma" in every .data[loop]. Actually the response json is quite big. Didn't post the entire thing here. – Siva Jun 27 '19 at 06:55
  • @Siva okay so that's exactly why you run into this error. You need to check for `gamma` key existence before you try to access further contents. Add an `if` check or something on top. – Nuhman Jun 27 '19 at 06:59
  • @Nuhman I am trying it like this. This is the block of code I am using. for(var loop =0; loop < pm.response.json().data.length; loop++) { if(pm.response.json().data[loop].gamma !== null){ console.log(pm.response.json().data[loop].gamma.sierra.data().id.length); } result=true; break; } I am at a loss. Quite new to this stuff. – Siva Jun 27 '19 at 07:10
  • @VedranMaricevic. could you please take a look and let me know now? I've edited the question. – Siva Jun 27 '19 at 09:49
  • @Nuhman could you please take a look and let me know now? I've edited the question. – Siva Jun 27 '19 at 09:50

4 Answers4

2

You could take a dynamic apporach and hand over the key of the object where you like to count a certain inner key.

function count(object, key, subKey) {
    const noObject = o => !o || typeof o !== 'object';

    function subCount(object) {
        if (noObject(object)) return 0;
        if (subKey in object) return 1;
        return Object.values(object).reduce((s, o) => s + subCount(o), 0);
    }

    if (noObject(object)) return 0;
    if (key in object) return subCount(object[key]);
    return Object.values(object).reduce((s, o) => s + count(o, key, subKey), 0);
}

var data = { data: [{ alpha: "a", beta: "b", delta: { cat: "dog" }, gamma: { sierra: { data: [{ type: "alphabet", id: "a" }, { type: "alphabet", id: "b" }] } } }] };

console.log(count(data, 'sierra', 'id')); // 2
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • This works for me :-) Thanks a ton! Could you please explain the logic behind this please? Help is very much appreciated. – Siva Jun 27 '19 at 10:12
  • it checks if a key exists and hands over to subCount or iterates all values and make a recursive call to `count`. if the key is foind, it looks for a wanted (sub) key and counts it by returning one. – Nina Scholz Jun 27 '19 at 10:54
  • This is literally the only solution I could find in a full day! – bjones01001101 Feb 11 '20 at 22:19
1

You can access it like this. If you have multiple data records you can use each loop to calculate as well.

a = {
 "data": [ 
 {
        "alpha": "a",
        "beta": "b",
        "delta": {
            "cat": "dog"
        },
        "gamma": {
            "sierra": {
                "data": [
                    {
                        "type": "alphabet",
                        "id": "a"
                    },
                    {
                        "type": "alphabet",
                        "id": "b"
                    }
                ]
            }
        }
    }
]
}

console.log(a.data[0].gamma.sierra.data.length);
Jaydeep
  • 1,686
  • 1
  • 16
  • 29
  • Apparently I did not make my question clear. Now I've edited with some more details. – Siva Jun 27 '19 at 10:04
0

You can use below code:

pm.response.json().data[0].gamma.sierra.data.filter( d => d.id ).length

Hope it helps.

Mohit Verma
  • 5,140
  • 2
  • 12
  • 27
  • What is "d" here? Could you please explain? – Siva Jun 27 '19 at 06:57
  • 1
    filter actually loops through data array and `d` just means the current element in the loop. – Nuhman Jun 27 '19 at 07:09
  • 1
    `d => d.id` means `function whatecer(d){ return d.id }` its basically a callback called on every array element - it checks if it has `id` and if it does it passes an element further to `.length` – Sławomir Ossowski Jun 27 '19 at 11:14
0
pm.response.json().data.map((item, loop) => {
    if(item.beta === "b" && item.gamma){ // check if gamma key is present

        console.log(item.gamma.sierra.data.filter(data => data.id).length); // 
    }
});

Jsfiddle

Nuhman
  • 1,172
  • 15
  • 22
  • TypeError: item.gamma.filter is not a function – Siva Jun 27 '19 at 08:17
  • This works but it gives the count of every sierra I have. I added the if loop to your code like this. `if(pm.response.json().data[loop].id===pm.variables.get("B")){ //your code here }` Still it gives the count as 2, 2. It does not seem to differentiate. – Siva Jun 28 '19 at 10:41
  • Remove your outer 'for' loop and check the updated code – Nuhman Jun 28 '19 at 11:05
  • It isn't going into the `if(item.gamma)` loop! – Siva Jun 28 '19 at 11:16
  • uhm, so what exactly is "loop" doing here? Is that the substitute of "for" loop? – Siva Jun 28 '19 at 11:27
  • No. It actually corresponds to the index of the loop like 0,1,2 etc. which we're not using here. So you may remove the `loop` keyword if you feel like. The closest 'substitute' of foor loop in this code is actually `map`. – Nuhman Jun 28 '19 at 11:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/195685/discussion-between-siva-and-nuhman). – Siva Jun 28 '19 at 11:42