I have a complex JSON that has nested objects and arrays.
E.g.
[
{
"Id": 1,
"Name": "Foo",
"Cached": true,
"Accessories": [2, 4, 16],
"Promo": [{"Type": 1, "Date": "null", "Priority": 1}, ...],
...
},
{
"Id": 2,
"Name": "Bar",
"Cached": false,
"Accessories": [16, 32, 64],
"Promo": [{"Type": 2, "Date": "null", "Priority": 2}, ...],
...
},
...
]
I want to iterate over each key (including nested objects and arrays) with JavaScript (using built-in features without 3rd-party libs), find the matching key and value (let’s say "Name" = "Bar"), and return the object that contains the matched result.
Assuming the key-value pair I’m looking for is unique, so returning the first match is fine.
I tried several different recursive functions, but couldn’t achieve the desired result.
The closest one was this https://medium.com/@alaneicker/how-to-process-json-data-with-recursion-dc530dd3db09
It iterates the entire structure properly but I can’t make it return the matched object.
upd. Best effort code (still doesn’t work as expected)
function loopThroughJSON(obj, searchKey, searchValue) {
if (typeof obj === 'string') {
obj = JSON.parse(obj);
}
for (var key in obj) {
if (typeof obj[key] === 'object') {
if (Array.isArray(obj[key])) {
for (var i = 0; i < obj[key].length; i++) {
return loopThroughJSON(obj[key][i], searchKey, searchValue);
}
} else {
return loopThroughJSON(obj[key], searchKey, searchValue);
}
} else {
if ((key === searchKey) && (obj[key] === searchValue)) {
return obj;
}
}
}
return null;
}
>Solution :
The problem with your code is you’re returning the prematured result inside the loop i.e. if the first item in the loop does not meet the condition, the function will return without checking the remaining items. A sample working recursive function would look something like:
function findObjectWithKeyAndVal(obj, key, value) {
// checking array
if (Array.isArray(obj)) {
for (let item of obj) {
const result = findObjectWithKeyAndVal(item, key, value);
if (result) {
return result;
}
}
} else if (typeof obj === 'object') {
// base case
if (obj[key] === value) {
return obj;
}
for (let item in obj) {
const result = findObjectWithKeyAndVal(obj[item], key, value);
if (result) {
return result;
}
}
}
return null;
}
const jsonData = [
{
"Id": 1,
"Name": "Foo",
"Cached": true,
"Accessories": [2, 4, 16],
"Promo": [{"Type": 1, "Date": "null", "Priority": 1}],
},
{
"Id": 2,
"Name": "Bar",
"Cached": false,
"Accessories": [16, 32, 64],
"Promo": [{"Type": 2, "Date": "null", "Priority": 2}],
},
];
const key = 'Name';
const value = 'Bar';
const result = findObjectWithKeyAndVal(jsonData, key, value);
console.log(result);