Convert nested JSON Object into a specific array format - javascript

I have nested JSON object looking like below and this JSON object I have to convert into some particular format which I have given below:
let jsonObj ={"data": {
"cardShop": {
"cardData": {
"cardTitle": "The Platinum Card<sup>®</sup>",
"cardType": "credit-cards",
"dtmProductName": "PlatinumCard",
"viewAllCards": {
"url": "credit-cards/all-cards",
"text": "All Cards"
}
},
"eligibilityChecker": {
"header": "Check your eligibility",
"subHeader": "The Platinum Card®",
"bulletPoints": [
"Only takes a couple of minutes to complete",
"Will not impact your credit rating",
"Allows you to apply with confidence"
]
}
}
}
}
And the above JSON object I have to convert it to the below format with some new properties like key, title, parentId, id, etc..
[
{
id: "cardShop",
key: "cardShop",
title: "cardShop",
selectable: false,
children: [
{
id: "cardData",
path:"cardShopCardData"
key: "cardData",
title: "cardData",
parentId: "cardShop",
selectable: false,
children: [
{
id: "cardTitle",
path :"cardShopcardDatacardTitle"
key: "cardTitle",
title: "cardTitle",
parentId: "cardData",
isLeaf: true,
children: []
},
{
id: "cardType",
key: "cardType",
title: "cardType",
parentId: "cardData",
isLeaf: true,
children: []
},
{
id: "dtmProductName",
key: "dtmProductName",
title: "dtmProductName",
parentId: "cardData",
isLeaf: true,
children: []
},
{
id: "viewAllCards",
key: "viewAllCards",
title: "viewAllCards",
parentId: "cardData",
selectable: false,
children: [
{
id: "url",
key: "url",
title: "url",
parentId: "viewAllCards",
isLeaf: true,
},
{
id: "text",
key: "text",
title: "text",
parentId: "viewAllCards",
isLeaf: true,
}
]
}
]
},
{
id: "eligibilityChecker",
key: "eligibilityChecker",
title: "eligibilityChecker",
parentId: "cardData",
selectable: false,
children: [
{
id: "header",
key: "header",
title: "header",
parentId: "eligibilityChecker",
},
{
id: "subHeader",
key: "subHeader",
title: "subHeader",
parentId: "eligibilityChecker",
},
{
id: "bulletPoints",
key: "bulletPoints",
title: "bulletPoints",
parentId: "eligibilityChecker",
},
{
id: "image",
key: "image",
title: "image",
parentId: "eligibilityChecker",
}
]
}
]
}
];
I have tried below things. For each object I need a parentId.
let prevKey =""
const iterate = (obj) => {
Object.keys(obj).forEach(key => {
if (typeof obj[key] === 'object' && obj[key] !== null) {
let c ={
id:key,
title:key,
selelected:false,
children:[]
};
if(prevKey && Object.keys(output).length === 0){
output ={
children :[]
}
output.children.push(c)
}
else if(prevKey ){
output.children.push(c)
} else{
output = c
}
prevKey = key;
iterate(obj[key])
}
else{
let c ={
id:key,
title:key,
selelected:false,
children:[]
};
output.children[0].children.push(c)
}
})
}
I have tried using recursion but somehow I am not able to get an expected output.

you can do something like this
const transform = data => {
const loop = (data, parent) => Object.entries(data).map(([key, value]) => {
let additional = parent? {
parentId: parent
}:{}
if(typeof value === 'object' && !Array.isArray(value)){
additional = {
...additional,
selectable: false,
children: loop(value, key)
}
}else{
additional.isLeaf = true
}
return {
id: key,
key,
title: key,
...additional
}
})
return loop(data)
}
let jsonObj = {
"data": {
"cardShop": {
"cardData": {
"cardTitle": "The Platinum Card<sup>®</sup>",
"cardType": "credit-cards",
"dtmProductName": "PlatinumCard",
"viewAllCards": {
"url": "credit-cards/all-cards",
"text": "All Cards"
}
},
"eligibilityChecker": {
"header": "Check your eligibility",
"subHeader": "The Platinum Card®",
"bulletPoints": [
"Only takes a couple of minutes to complete",
"Will not impact your credit rating",
"Allows you to apply with confidence"
]
}
}
}
}
console.log(transform(jsonObj.data))

Related

Extract data from json with 2 properties with same name

I have a complex deeply nested JSON in Node.js and I have trouble extracting certain data. I need all the ids that belong only to the items, my problem is that the folders also have an id field so I cannot access only the id from the items. This is an example json:
{
id: "0",
name: null,
parentId: null,
folderType: "chatCannedMessages",
folders: [
{
id: 3195588631115178,
name: "Testfolder",
parentId: null,
folderType: "chatCannedMessages",
folders: [
{
id: "3195588620182363",
name: "Subfolder",
parentId: "3195588631115178",
folderType: "chatCannedMessages",
folders: [
{
id: "3206824598737435",
name: "Interesting",
parentId: "3195588620182363",
folderType: "chatCannedMessages",
folders: [],
items: [
{
id: "3208409930553392",
name: "Canned Message",
folderId: "3206824598737435",
updated: "2022-05-27T07:28:40.450Z",
frontendFolderId: null,
text: "<p>This is an HTML with Image.</p>",
keywords: "test",
subject: "What kind of subject",
slashCommand: "test",
language: "en-US",
setupItemId: "3208409930553392",
},
],
},
],
items: [
{
id: "3195595211854821",
name: "Message in subfolder",
folderId: "3195588620182363",
updated: "2022-05-19T12:05:39.503Z",
frontendFolderId: null,
text: "Message in subfolder",
keywords: "test",
subject: "Message in subfolder",
slashCommand: "sub",
language: "bn-BD",
setupItemId: "3195595211854821",
},
],
},
],
items: [],
},
],
items: [
{
id: "2888102250465731",
name: "bye",
folderId: null,
updated: "2022-05-25T11:15:36.367Z",
frontendFolderId: null,
text: "Thanks for contacting us. Please do not hesitate to contact us again if we can be of further assistance.",
keywords: "bye",
subject: null,
slashCommand: null,
language: null,
setupItemId: "2888102250465731",
},
],
};
The output that I want to achieve here is an array, looking like this:
["3208409930553392", "3195595211854821", null]
Iterate it is not that complex json. Just items and folders.
var obj={id:"0",name:null,parentId:null,folderType:"chatCannedMessages",folders:[{id:0xb5a5ef534b5aa,name:"Testfolder",parentId:null,folderType:"chatCannedMessages",folders:[{id:"3195588620182363",name:"Subfolder",parentId:"3195588631115178",folderType:"chatCannedMessages",folders:[{id:"3206824598737435",name:"Interesting",parentId:"3195588620182363",folderType:"chatCannedMessages",folders:[],items:[{id:"3208409930553392",name:"Canned Message",folderId:"3206824598737435",updated:"2022-05-27T07:28:40.450Z",frontendFolderId:null,text:"<p>This is an HTML with Image.</p>",keywords:"test",subject:"What kind of subject",slashCommand:"test",language:"en-US",setupItemId:"3208409930553392"},]},],items:[{id:"3195595211854821",name:"Message in subfolder",folderId:"3195588620182363",updated:"2022-05-19T12:05:39.503Z",frontendFolderId:null,text:"Message in subfolder",keywords:"test",subject:"Message in subfolder",slashCommand:"sub",language:"bn-BD",setupItemId:"3195595211854821"},]},],items:[]},],items:[{id:"2888102250465731",name:"bye",folderId:null,updated:"2022-05-25T11:15:36.367Z",frontendFolderId:null,text:"Thanks for contacting us. Please do not hesitate to contact us again if we can be of further assistance.",keywords:"bye",subject:null,slashCommand:null,language:null,setupItemId:"2888102250465731"},]};
result = [];
function iterate(obj) {
(obj.items || []).forEach(function(item) {
result.push(item.id)
});
(obj.folders || []).forEach(function(item) {
iterate(item)
});
}
iterate(obj);
console.log(result)
const data = {
id: "0",
name: null,
parentId: null,
folderType: "chatCannedMessages",
folders: [{
id: 3195588631115178,
name: "Testfolder",
parentId: null,
folderType: "chatCannedMessages",
folders: [{
id: "3195588620182363",
name: "Subfolder",
parentId: "3195588631115178",
folderType: "chatCannedMessages",
folders: [{
id: "3206824598737435",
name: "Interesting",
parentId: "3195588620182363",
folderType: "chatCannedMessages",
folders: [],
items: [{
id: "3208409930553392",
name: "Canned Message",
folderId: "3206824598737435",
updated: "2022-05-27T07:28:40.450Z",
frontendFolderId: null,
text: "<p>This is an HTML with Image.</p>",
keywords: "test",
subject: "What kind of subject",
slashCommand: "test",
language: "en-US",
setupItemId: "3208409930553392",
}, ],
}, ],
items: [{
id: "3195595211854821",
name: "Message in subfolder",
folderId: "3195588620182363",
updated: "2022-05-19T12:05:39.503Z",
frontendFolderId: null,
text: "Message in subfolder",
keywords: "test",
subject: "Message in subfolder",
slashCommand: "sub",
language: "bn-BD",
setupItemId: "3195595211854821",
}, ],
}, ],
items: [],
}, ],
items: [{
id: "2888102250465731",
name: "bye",
folderId: null,
updated: "2022-05-25T11:15:36.367Z",
frontendFolderId: null,
text: "Thanks for contacting us. Please do not hesitate to contact us again if we can be of further assistance.",
keywords: "bye",
subject: null,
slashCommand: null,
language: null,
setupItemId: "2888102250465731",
}, ],
};
const ids = []
function traverse(obj, parent) {
if (obj === null) return
if (Array.isArray(obj)) {
for (const item of obj) {
traverse(item, parent)
}
} else if (typeof obj === 'object') {
if (parent === 'items') {
ids.push(obj.id)
} else {
for (const [key, value] of Object.entries(obj)) {
traverse(value, key)
}
}
}
}
traverse(data, '')
console.log(ids)
You can solve your problem by applying a recursive logic. The pattern is that if the last descendant object was items, then any direct object descendants (with possible arrays in-between of the hierarchy) are having ids that we need to collect
let input = {
items: [
{
id: 1,
foo: [
{
id: 2,
items: [
{
id: 3,
items: [
{
bar: [
{
id: 4
}
]
},
{
id: 5
}
]
}
]
}
]
}
]
}
let ids = [];
function getItemIDs(obj, wasItems = false) {
if (Array.isArray(obj) || (typeof obj === "object")) {
if (wasItems && (!Array.isArray(obj))) {
ids.push(obj.id);
}
for (let key in obj) {
if (Array.isArray(obj[key]) || (typeof obj[key] === "object")) {
getItemIDs(obj[key], (key === "items") || (wasItems && !Array.isArray(obj[key])))
}
}
}
}
getItemIDs(input);
console.log(ids);

ReactJs: Filtering nested objects

How do I filter nested objects in React? Currently my function is only looking for the main title, not the nested ones.
export const treeData = [
{
title: 'Orange',
key: '0-0',
children: [
{
title: 'Anu',
key: '0-0-0',
isLeaf: true,
},
{
title: 'Anurag',
key: '0-0-1',
isLeaf: true,
},
],
},
{
title: 'ABC',
key: '0-1',
children: [
{
title: 'leaf 1-0',
key: '0-1-0',
isLeaf: true,
},
{
title: 'leaf 1-1',
key: '0-1-1',
isLeaf: true,
},
],
},
]
export default {
treeData,
}
and the function is:
const filtered = treeData.filter((data) => {
return data.title.toLowerCase().includes(e.target.value.toLowerCase())
})
So currently it is only searching the Orange and ABC, not the titles from children.
I recommend flattening the title values and then filtering. Note, the end result will contain a mixture of top level "parent" data and children.
const flattened = treeData.reduce((acc, data) => {
acc.push(data, ...data.children)
return acc;
}, []);
const filtered = flattened.filter((data) => {
return data.title.toLowerCase().includes(e.target.value.toLowerCase())
})
If you only need a filtered list of top level data, you will need to do something like the following:
function dataIncludesTitle(data, title) {
return data.title.toLowerCase().includes(title);
}
const searchValue = e.target.value.toLowerCase();
const filtered = treeData.filter((data) => {
return dataIncludesTitle(data, searchValue) || data.children.some(child => dataIncludesTitle(child, searchValue));
})
Something like:
const filtered = treeData.filter((data) => {
return data.title.toLowerCase().includes(e.target.value.toLowerCase()) ||
data.children.filter(x => x.title.toLowerCase().includes(e.target.value.toLowerCase())).length > 0
})
Look into data.children filtering subobject's title that contains e.target.value.toLowerCase().
If you want to get full objects containing child objects with a title similar to the search string, try this:
const treeData = [
{
title: 'Orange',
key: '0-0',
children: [
{
title: 'Anu',
key: '0-0-0',
isLeaf: true,
},
{
title: 'Anurag',
key: '0-0-1',
isLeaf: true,
},
],
},
{
title: 'ABC',
key: '0-1',
children: [
{
title: 'leaf 1-0',
key: '0-1-0',
isLeaf: true,
},
{
title: 'leaf 1-1',
key: '0-1-1',
isLeaf: true,
},
],
},
];
const searchString = 'ANUR';
const filtered = treeData.filter((datum) => {
const filteredChilds = datum.children.filter((child) => child.title.toLowerCase().includes(searchString.toLowerCase()));
return filteredChilds.length > 0;
});
console.log(filtered);
If you want to get these objects and only matched child objects try this:
const treeData = [{
title: 'Orange',
key: '0-0',
children: [{
title: 'Anu',
key: '0-0-0',
isLeaf: true,
},
{
title: 'Anurag',
key: '0-0-1',
isLeaf: true,
},
],
},
{
title: 'ABC',
key: '0-1',
children: [{
title: 'leaf 1-0',
key: '0-1-0',
isLeaf: true,
},
{
title: 'leaf 1-1',
key: '0-1-1',
isLeaf: true,
},
],
},
];
const searchString = 'ANUR';
const filtered = treeData.map((datum) => {
const filteredChilds = datum.children.filter((child) => child.title.toLowerCase().includes(searchString.toLowerCase()));
return {
...datum,
children: filteredChilds
};
}).filter(datum => datum.children.length > 0);
console.log(filtered);
If you want to get only matched child objects try this:
const treeData = [{
title: 'Orange',
key: '0-0',
children: [{
title: 'Anu',
key: '0-0-0',
isLeaf: true,
},
{
title: 'Anurag',
key: '0-0-1',
isLeaf: true,
},
],
},
{
title: 'ABC',
key: '0-1',
children: [{
title: 'leaf 1-0',
key: '0-1-0',
isLeaf: true,
},
{
title: 'leaf 1-1',
key: '0-1-1',
isLeaf: true,
},
],
},
];
const searchString = 'ANUR';
const filtered = treeData.reduce((acc, datum) => acc.concat(datum.children.filter((child) => child.title.toLowerCase().includes(searchString.toLowerCase()))), []);
console.log(filtered);

How to filter nested arrays by searching

I have an array of objects that I want to filter by comparing a nested property to a search term.
For example:
let array = [
{
category: 15,
label: "Components",
value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
children: [
{
category: 1,
label: "Carousel1",
diId: 55946,
// as you can see there are many children nested array of object
children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
},
{
category: 2,
label: "Checkbox1",
diId: 193909,
children: [{ label: "datafound", value: "47d18sb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "045e8786-2165-4e1e-a839-99b1b0ceef57"
}
]
},
{
value: "4be22726-850c-4905-ab3b-039fcf607d55",
label: "Default",
children: [
{
category: 5,
defaultValueType: 1,
label: "Empty",
toType: "String",
value: "ebedb43f-4c53-491f-8954-d030321845cd"
},
{
category: 5,
defaultValueType: 2,
label: "Space",
toType: "String",
value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
},
{
category: 5,
defaultValueType: 8,
label: "Current Username",
toType: "String",
value: "25f6b40a-33c7-4f17-b29d-99e8d1e4e33c"
},
{
category: 5,
defaultValueType: 9,
label: "Current Location",
toType: "Location",
value: "ed59da2f-318d-4599-9085-4d9d769a27d7"
}
]
},
{
category: 4,
label: "Fixed Value",
isFixed: true,
value: "28e90e3e-a20b-4499-9593-061a7d1e7bd6"
// as you can see there is no children in this object
}
]};
What I'm trying to achieve is if I search for 'nodata' for example my result should be
let array = [
{
category: 15,
label: "Components",
value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
children: [
{
category: 1,
label: "Carousel1",
diId: 55946,
// as you can see there are many children nested array of object
children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
}
]
}
];
Another option if I search for 'spa' my result should be
let array = [
{
value: "4be22726-850c-4905-ab3b-039fcf607d55",
label: "Default",
children: [
{
category: 5,
defaultValueType: 2,
label: "Space",
toType: "String",
value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
}
]
}
];
I have been super confused and I decided to get some help. Thank you for your helps guys!
The following function should do the trick for you:
function searchData(dataArray, searchTerm) {
return dataArray.flatMap(obj => {
const objHasSearchTerm = Object.entries(obj)
.some(([key, value]) => key !== 'children' && String(value).toLowerCase().includes(searchTerm.toLowerCase()));
if (objHasSearchTerm && !obj.children) return [obj];
const matchedChildren = searchData(obj.children ?? [], searchTerm);
return objHasSearchTerm || matchedChildren.length > 0
? [{
...obj,
children: matchedChildren,
}]
: [];
})
}
It recursively goes through the data array, looks for any entries that have the specified search term, and if so, places it into the newly constructed object. It will preserve the nested shape of the object, which may or may not be what is needed. Feel free to tweak the algorithm to your own needs.
let allData = [
{
category: 15,
label: "Components",
value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
children: [
{
category: 1,
label: "Carousel1",
diId: 55946,
// as you can see there are many children nested array of object
children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
},
{
category: 2,
label: "Checkbox1",
diId: 193909,
children: [{ label: "datafound", value: "47d18sb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "045e8786-2165-4e1e-a839-99b1b0ceef57"
}
]
},
{
value: "4be22726-850c-4905-ab3b-039fcf607d55",
label: "Default",
children: [
{
category: 5,
defaultValueType: 1,
label: "Empty",
toType: "String",
value: "ebedb43f-4c53-491f-8954-d030321845cd"
},
{
category: 5,
defaultValueType: 2,
label: "Space",
toType: "String",
value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
},
{
category: 5,
defaultValueType: 8,
label: "Current Username",
toType: "String",
value: "25f6b40a-33c7-4f17-b29d-99e8d1e4e33c"
},
{
category: 5,
defaultValueType: 9,
label: "Current Location",
toType: "Location",
value: "ed59da2f-318d-4599-9085-4d9d769a27d7"
}
]
},
{
category: 4,
label: "Fixed Value",
isFixed: true,
value: "28e90e3e-a20b-4499-9593-061a7d1e7bd6"
// as you can see there is no children in this object
}
];
function searchData(dataArray, searchTerm) {
return dataArray.flatMap(obj => {
const objHasSearchTerm = Object.entries(obj)
.some(([key, value]) => key !== 'children' && String(value).toLowerCase().includes(searchTerm.toLowerCase()));
if (objHasSearchTerm && !obj.children) return [obj];
const matchedChildren = searchData(obj.children ?? [], searchTerm);
return objHasSearchTerm || matchedChildren.length > 0
? [{
...obj,
children: matchedChildren,
}]
: [];
})
}
console.log('----- Search: nodata')
console.log(JSON.stringify(searchData(allData, 'nodata'), null, 2))
console.log('----- Search: spa')
console.log(JSON.stringify(searchData(allData, 'spa'), null, 2))

How to sort nested array object using another nested array of on the basis of id?

My objective here is to convert the input array into the structure of the output array.
The input array and output array are shown below. If you observe carefully we can see that id is common in both the arrays and only title changes.
var output = [{
id: "1",
title: 'title',
children: [],
},
{
id: "2",
title: 'title2',
children: [],
},
{
id: "3",
title: 'title3',
children: [{
id: "4",
title: 'title4',
children: [],
}, {
id: "5",
title: 'title5',
children: [{
id: "6",
title: 'title6',
children: [],
}, {
id: "7",
title: 'title7',
children: [],
}, {
id: "9",
title: 'title9',
children: [],
}]
}],
}
]
var input = [{
id: "1",
title: 'title_chnaged',
children: [],
},
{
id: "2",
title: 'title_changed',
children: []
},
{
id: "3",
title: 'title_changed',
children: [{
id: "4",
title: 'title_changed',
children: [],
}, {
id: "5",
title: 'title_changed',
children: [],
children: [{
id: "6",
title: 'title_changed',
children: [],
},
{
id: "7",
title: 'title_changed',
children: [],
}
]
}],
},
{
id: "9",
title: 'title_chnaged',
children: [],
}
]
This function will look into the input array of corresponding element of output array on the . basis of id
let found;
function findTheKey(id, widget) {
let newObj = [...widget];
for (var key in newObj) {
if (newObj[key]["id"] == id) {
found = newObj[key];
break;
}
if (newObj[key].hasOwnProperty("children")) {
findTheKey(id, newObj[key].children);
}
}
return found;
}
This function will iterate over the output array and look for corresponding element in input array
function findAllObjectOnArray(output) {
let newObj = [...output];
for (let key in newObj) {
newObj[key] = {
...findTheKey(newObj[key]['id'], input),
children: newObj[key].children
};
if (newObj[key].hasOwnProperty("children")) {
findAllObjectOnArray(newObj[key].children, input);
}
}
return newObj;
}
var result = findAllObjectOnArray(output)
console.log(result)
The result is as expected on label 1 but as we move into nested object, it didn't changed.
Please suggest me something which will let it work. Any hint or solution is highly welcome ?
I've created a function fn that maps array elements to elemnts with property title = "title"+id and then recursively maps children nodes.
var output = [
{
id: "1",
title: 'title',
children: [],
},
{
id: "2",
title: 'title2',
children: [],
},
{
id: "3",
title: 'title3',
children: [
{
id: "4",
title: 'title4',
children: [],
},
{
id: "5",
title: 'title5',
children: [
{
id: "6",
title: 'title6',
children: [],
},
{
id: "7",
title: 'title7',
children: [],
},
{
id: "9",
title: 'title9',
children: [],
}]
}],
}]
var input = [
{
id: "1",
title: 'title_chnaged',
children: [],
},
{
id: "2",
title: 'title_changed',
children: []
},
{
id: "3",
title: 'title_changed',
children: [
{
id: "4",
title: 'title_changed',
children: [],
},
{
id: "5",
title: 'title_changed',
children: [],
children: [
{
id: "6",
title: 'title_changed',
children: [],
},
{
id: "7",
title: 'title_changed',
children: [],
}]
}],
},
{
id: "9",
title: 'title_chnaged',
children: [],
}]
var fn = node =>
node && node.map( x =>
({
...x,
title: "title"+x.id,
children: fn(x.children)
})
)
var result = fn(output)
console.log(result)
A tip: Either stick to immutable (copy all objects) or modify it in-place. Things become really complicated when you mix the two unless you know what you are doing.
I'm not entirely sure if this is what you mean? It's hard to be sure if it works correctly because the title_changed strings are all the same.
I just added newObj[key].children = findAllObjectOnArray(newObj[key].children); so that the children property gets updated correctly (since you make a clone of the array on every call, so children doesn't get updated when you try to modify it by reference).
var output = [
{
id: "1",
title: 'title',
children: [],
},
{
id: "2",
title: 'title2',
children: [],
},
{
id: "3",
title: 'title3',
children: [
{
id: "4",
title: 'title4',
children: [],
},
{
id: "5",
title: 'title5',
children: [
{
id: "6",
title: 'title6',
children: [],
},
{
id: "7",
title: 'title7',
children: [],
},
{
id: "9",
title: 'title9',
children: [],
}]
}],
}]
var input = [
{
id: "1",
title: 'title_chnaged',
children: [],
},
{
id: "2",
title: 'title_changed',
children: []
},
{
id: "3",
title: 'title_changed',
children: [
{
id: "4",
title: 'title_changed',
children: [],
},
{
id: "5",
title: 'title_changed',
children: [],
children: [
{
id: "6",
title: 'title_changed',
children: [],
},
{
id: "7",
title: 'title_changed',
children: [],
}]
}],
},
{
id: "9",
title: 'title_chnaged',
children: [],
}]
let found;
function findTheKey(id, widget) {
let newObj = [...widget];
for (var key in newObj) {
if (newObj[key]["id"] == id) {
found = newObj[key];
break;
}
if (newObj[key].hasOwnProperty("children")) {
findTheKey(id, newObj[key].children);
}
}
return found;
}
function findAllObjectOnArray(output) {
let newObj = [...output];
for (let key in newObj) {
newObj[key] = {
...findTheKey(newObj[key]['id'], input),
children: newObj[key].children
};
if (newObj[key].hasOwnProperty("children")) {
newObj[key].children = findAllObjectOnArray(newObj[key].children);
}
}
return newObj;
}
var result = findAllObjectOnArray(output)
console.log(result)

Why code after return statement executing inside for-in loop in javascript?

my variable look like this
var widgets2 = [{
id: "1",
title: 'title',
children: [],
},
{
id: "2",
title: 'title2',
children: []
},
{
id: "3",
title: 'title3',
children: [{
id: "4",
title: 'title4',
children: [],
}, {
id: "5",
title: 'title5',
children: [],
children: [{
id: "6",
title: 'title6',
children: [],
},
{
id: "7",
title: 'title7',
children: [],
}
]
}],
},
{
id: "9",
title: 'title9',
children: [],
}
]
The function code look like this
function findTheKey(id,widget){
let newObj=[...widget];
for(var key in newObj){
if(newObj[key]['id']==id){
console.log(newObj[key])
return newObj[key];
}
console.log("came here")
if(newObj[key].hasOwnProperty("children")){
findTheKey(id,newObj[key].children);
}
}
}
When the called the function using following code
var result=findTheKey(4,widgets2);
console.log(result)
The result look like this
{id: "4", title: "title4", children: Array(0)}
came here
That means even after executing return statement, console.log getting executed, any help will be highly appreciated.
Thankyou
Since this is a recursive function, the return does not have the effect you expect, you need a variable outside the recursive function to keep the current state of what you want to find.
See the snippet below for example:
var widgets2 = [
{
id: "1",
title: "title",
children: [],
},
{
id: "2",
title: "title2",
children: [],
},
{
id: "3",
title: "title3",
children: [
{
id: "4",
title: "title4",
children: [],
},
{
id: "5",
title: "title5",
children: [],
children: [
{
id: "6",
title: "title6",
children: [],
},
{
id: "7",
title: "title7",
children: [],
},
],
},
],
},
{
id: "9",
title: "title9",
children: [],
},
];
let found;
function findTheKey(id, widget) {
let newObj = [...widget];
for (var key in newObj) {
if (newObj[key]["id"] == id) {
found = newObj[key];
break;
}
if (newObj[key].hasOwnProperty("children")) {
findTheKey(id, newObj[key].children);
}
}
return found;
}
var result = findTheKey(4, widgets2);
console.log(result);
You should update your question for this, but since you asked for it in the comments, here is what I propose.
function findTheKey(id, widget) {
const newObj = [...widget];
for (const key in newObj) {
if (newObj[key]["id"] === `${id}`) {
return newObj[key];
}
if (newObj[key].hasOwnProperty('children')) {
/* Use the result of the recursive function */
const foundObject = findTheKey(id, newObj[key].children);
if(foundObject) return foundObject;
}
}
return false;
}

Categories