Going through a JSON response to find specific data and saving id as variable

Hi,

I made a request that in a response gets a JSON that is a structure of an organization (arrays and data). My goal is to go through it to find a positon with specific name and check if it has a person assigned to it.
If I find the first position that name is correct (“name”: “Test”) and there is no person assigned (“personData”: null) then I wish to get the position id and save it as vairable, so I could use it in other requests.

It is very complicated for me, as I still lack the knowledge and experience in JS and Postman.

In the example below the position id that I look for would be in the last part of the JSNON (“id”: 12)
But this isn’t usually a case, it may be nested deeper or not and not always at the end.

{
	"correctExecution": null,
	"structure": {
		"data": {
			"id": -1,
			"version": null,
			"name": "Company",
			"type": "COMP",
			"exactMatch": false,
			"assignedToPerson": false,
			"personData": null
		},
		"children": [
			{
				"data": {
					"id": 0,
					"version": null,
					"name": "Organization 1",
					"type": "ORG",
					"exactMatch": false,
					"assignedToPerson": false,
					"personData": null
				},
				"children": [
					{
						"data": {
							"id": 1,
							"version": 0,
							"name": "Organization 2",
							"type": "ORG",
							"exactMatch": false,
							"assignedToPerson": false,
							"personData": null
						},
						"children": [
							{
								"data": {
									"id": 2,
									"version": 0,
									"name": "Inspector 1",
									"type": "POSITION",
									"exactMatch": false,
									"assignedToPerson": true,
									"personData": {
										"name": "John"
									}
								},
								"children": null
							},
							{
								"data": {
									"id": 9,
									"version": 0,
									"name": "Inspector 2",
									"type": "POSITION",
									"exactMatch": false,
									"assignedToPerson": true,
									"personData": {
										"name": "Will"
									}
								},
								"children": null
							}
						]
					},
					{
						"data": {
							"id": 3,
							"version": 0,
							"name": "Organization 3",
							"type": "ORG",
							"exactMatch": false,
							"assignedToPerson": false,
							"personData": null
						},
						"children": [
							{
								"data": {
									"id": 4,
									"version": 0,
									"name": "Inspector 4",
									"type": "POSITION",
									"exactMatch": false,
									"assignedToPerson": true,
									"personData": {
										"name": "Anna"
									}
								},
								"children": null
							}
						]
					},
					{
						"data": {
							"id": 10,
							"version": 0,
							"name": "Organization 4",
							"type": "ORG",
							"exactMatch": false,
							"assignedToPerson": false,
							"personData": null
						},
						"children": [
							{
								"data": {
									"id": 11,
									"version": 0,
									"name": "Staff 1",
									"type": "POSITION",
									"exactMatch": false,
									"assignedToPerson": true,
									"personData": {
										"name": "George"
									}
								},
								"children": null
							},
							{
								"data": {
									"id": 12,
									"version": 0,
									"name": "Test",
									"type": "POSITION",
									"exactMatch": false,
									"assignedToPerson": true,
									"personData": null
								},
								"children": null
							}
						]
					}
				]
			}
		]
	}
}

I’ve tried to combine a few solutions that I found here, with different functions. I tried to find the elements with lodash _.find _.filter. But I failed. I could find just a name or check if there is a personData.

Any help would be appreciated.

I can help you with this. Let me know if you would like to jump on a call.

P.S. You should include the e.g. example in your example.

Hey Alex,

I haven’t found a solution, but I did found a workaround for the problem.
The problem for me was how deep was the position in json. So I assigned the position not so deep, so it would be easier to find.

In this case my json file looked like this one below, with last element being the positon I look for.

let response = {

"correctExecution": null,

"structure": {

    "data": {

        "id": -1,

        "version": null,

        "name": "Company",

        "type": "COMP",

        "exactMatch": false,

        "assignedToPerson": false,

        "personData": null

    },

    "children": [

        {

            "data": {

                "id": 0,

                "version": null,

                "name": "Organization 1",

                "type": "ORG",

                "exactMatch": false,

                "assignedToPerson": false,

                "personData": null

            },

            "children": [

                {

                    "data": {

                        "id": 1,

                        "version": 0,

                        "name": "Organization 2",

                        "type": "ORG",

                        "exactMatch": false,

                        "assignedToPerson": false,

                        "personData": null

                    },

                    "children": [

                        {

                            "data": {

                                "id": 2,

                                "version": 0,

                                "name": "Inspector 1",

                                "type": "POSITION",

                                "exactMatch": false,

                                "assignedToPerson": true,

                                "personData": {

                                    "name": "John"

                                }

                            },

                            "children": null

                        },

                        {

                            "data": {

                                "id": 9,

                                "version": 0,

                                "name": "Inspector 2",

                                "type": "POSITION",

                                "exactMatch": false,

                                "assignedToPerson": true,

                                "personData": {

                                    "name": "Will"

                                }

                            },

                            "children": null

                        }

                    ]

                },

                {

                    "data": {

                        "id": 3,

                        "version": 0,

                        "name": "Organization 3",

                        "type": "ORG",

                        "exactMatch": false,

                        "assignedToPerson": false,

                        "personData": null

                    },

                    "children": [

                        {

                            "data": {

                                "id": 4,

                                "version": 0,

                                "name": "Inspector 4",

                                "type": "POSITION",

                                "exactMatch": false,

                                "assignedToPerson": true,

                                "personData": {

                                    "name": "Anna"

                                }

                            },

                            "children": null

                        }

                    ]

                },

                {

                    "data": {

                        "id": 10,

                        "version": 0,

                        "name": "Organization 4",

                        "type": "ORG",

                        "exactMatch": false,

                        "assignedToPerson": false,

                        "personData": null

                    },

                    "children": [

                        {

                            "data": {

                                "id": 11,

                                "version": 0,

                                "name": "Staff 1",

                                "type": "POSITION",

                                "exactMatch": false,

                                "assignedToPerson": true,

                                "personData": {

                                    "name": "George"

                                }

                            },

                            "children": null

                        },

                        {

                            "data": {

                                "id": 12,

                                "version": 0,

                                "name": "Test",

                                "type": "POSITION",

                                "exactMatch": false,

                                "assignedToPerson": true,

                                "personData": null

                            },

                            "children": null

                        }

                    ]

                }

            ]

        },

        {

            "data": {

                "id": 5,

                "version": null,

                "name": "Test",

                "type": "ORG",

                "exactMatch": false,

                "assignedToPerson": false,

                "personData": null

            },

            "children": null

        }

    ]

}

}

And with this structure I was able to find what I looked for

pm.test(“Test”, function () {

let positionStatus = false;

response.structure.children.some((item, index) => {

    console.log(item.data.name)

    if (item.data.name === 'Test') {

        if (item.data.personData === null) {

            positionStatus = true;

            console.log(index, item.data.id);

            pm.environment.set("id", item.data.id);

        }

    }

});

pm.expect(positionStatus).to.eql(true);

});

As I understand, with multiple elements that would meet the required name and personData I would get the last element this function finds. Which is fine for me.

The perfect solution would be if I could just look through the whole json file, find an element that has exact name and personData wherever it is, and get that id.
But that’s way complicated for me.
The question is, is there any way to write it better?

Hey @Matt1991,

Your “structure” is essentially recursive (your data has children, which can have data with children, which can have data with children, …), so it’s best addressed by a recursive algorithm.

If you can define a function that will find the data with the name you’re looking for in a list of objects, or their children, and return that data, you’ve basically got what you need. This would have to be a recursive function: a function that calls itself under certain conditions. Something like this:

function findPosition(var positions, var name) {
  for (let position of positions) {
    if (position.data.name == name) {
      return position.data;  // Done, found it!
    }
    // Search all the children as well
    let foundInChildren = findPosition(position.data.children, name);  // This is the recursive call where the function calls itself
    if (foundInChildren != null) {
      return foundInChildren;
    }
  }
  return null;
}

Then you can call this function as

findPosition([pm.response.json().structure]);

If it finds something, it will return the data structure (you can then get the position id or personData from it. If it doesn’t find anything, it will return null.

Disclaimer: I haven’t tested this code, it’s just to show a possible way of solving this at a “pseudo-code” level.

Hope this helps,
Frans

2 Likes

Hey @fransf-wtax. Thank you for an idea.
I did work a bit with it and I made it work until a point when I got an error.
positions is not iterable
In your example we look for a children that is not null but at some point I can get an empty object, and if so then it should go to check the next children. I guess thats where the error comes from.

I have no clue what to do with it. I’d tried to use some break, continue with labels, but it didn’t work as intended. Any help would be appreaciated :slight_smile:

Here is what I work with.

Response

{
    "correctExecution": null,
    "structure": {
        "data": {
            "id": -1,
            "version": null,
            "name": "Org 1",
            "type": "ORGANIZATION",
            "personData": null
        },
        "children": [
            {
                "data": {
                    "id": 0,
                    "version": null,
                    "name": "Org 2",
                    "type": "ORGANIZATION",
                    "personData": null
                },
                "children": [
                    {
                        "data": {
                            "id": 1,
                            "version": 0,
                            "name": "Position 1",
                            "type": "POSITION",
                            "personData": {
                                "name": "Anna",
                                "cn": "111"
                            }
                        },
                        "children": null
                    },
                    {
                        "data": {
                            "id": 2,
                            "version": 0,
                            "name": "Org 3",
                            "type": "ORGANIZATION",
                            
                            "personData": null
                        },
                        "children": [
                            {
                                "data": {
                                    "id": 3,
                                    "version": 0,
                                    "name": "Position 2",
                                    "type": "POSITION",
                                    "personData": null
                                },
                                "children": null
                            }
                        ]
                    },
                    {
                        "data": {
                            "id": 4,
                            "version": 0,
                            "name": "Test",
                            "type": "POSITION",
                            "personData": null
                        },
                        "children": null
                    },
                    {
                        "data": {
                            "id": 5,
                            "version": 0,
                            "name": "Org 4",
                            "type": "ORGANIZATION",
                            "personData": null
                        },
                        "children": [
                            {
                                "data": {
                                    "id": 7,
                                    "version": 0,
                                    "name": "Position 3",
                                    "type": "POSITION",
                                    "personData": null
                                },
                                "children": null
                            },
                            {
                                "data": {
                                    "id": 6,
                                    "version": 1,
                                    "name": "Position 4",
                                    "type": "POSITION",
                                    "personData": {
                                        "name": "John",
                                        "cn": "123"
                                    }
                                },
                                "children": null
                            }
                        ]
                    }
                ]
            }
        ]
    }
}

Here is the Test

let responseJson = pm.response.json();
function findPosition(positions, name) {
    for (let position of positions) {
        if ((position.data.name === name) && (position.data.personData === null)){
            console.log('id: '+ position.data.id);
            pm.environment.set("id", position.data.id);
            return position.data;
        }
        let foundInChildren = findPosition(position.children, name);
        if (foundInChildren != null) {
            return foundInChildren;
        }
    }
    return null;
};
findPosition([responseJson.structure], 'Test')

@Matt1991 I think you’ve already given the answer yourself: if position.children is null you shouldn’t recursively call the function, because there are no children to recurse into.

Just add an if statement to that effect around the block that does the recursion and you should be good.
e.g.

if (position.children != null) {
  let foundInChildren = findPosition(position.children, name);
  if (foundInChildren != null) {
    return foundInChildren;
  }
}
1 Like

Can you provide what you tried here? Lodash _.find seems like the right tool to use in this situation.

Just as a general local troubleshooting approach, it’s always a good idea to console.log your object. Start slow and simple with something like:

var jsonData = pm.response.json()
var foo = _.find(jsonData, {"name":"Test"});
console.log(foo) 
1 Like

Hey @murdoc.trammell,
I can only say that I tried to use _.find but the problem is that the structure has an arrays in different places, and I couldn’t go through the elements in it. I had to specify exactly the place where I want to look into.

Example, if I look for “Org 1” i get my result, but if I look for an “Org 2” that is inside a children that has arrays as a result I get undefined.

var jsonData = pm.response.json()
var foo = _.find(jsonData.data.structure, {"name":"Org 1"});
console.log(foo)

Here is the examle request in JSON format.
https://www.getpostman.com/collections/9cb254b848cc48e87846

Hey @fransf-wtax , you are right.
The solution you provided it’s what I looked for. Guess I overthinked it a bit.
It seemed so easy but I feel it’s still complicated, I will try to consol.log it more to understand it better. Thank you.

Without full context, that sounds a bit like a schema problem with your APIs. While it can be worked around using JS to find the right nested object like @fransf-wtax suggested - I would question if it should be and talk with your devs about it. Think about it from the perspective of another developer trying to work with this endpoint.

1 Like