I have nested JSON
[
{
"heading": [
{
"name": "Heading 01",
"Items": [
{
"name": "Item 01",
"layers": [
{
"name": "layer01",
},
{
"name": "layer02",
}
]
}
]
}
]
}
]
I am trying to push id, parent and draggable key value pair to nested JSON and output should be like this
[{
"id": 1,
"parent": 0,
"droppable":true,
"heading": [
{
"name": "Heading 01",
"id": 2,
"parent": 1,
"droppable":true,
"Items": [
{
"name": "Item 01",
"id": 3,
"parent": 2,
"droppable":true,
"layers": [
{
"name": "layer01",
"parent": 3,
"id":4,
"droppable":false
},
{
"name": "layer02",
"parent": 3,
"id":4,
"droppable":false
}
]
}
]
}
]
}]
But when I tried using arr.forEach
I am not getting the expected output.
let treedata = [
{
"heading": [
{
"name": "Heading 01",
"Items": [
{
"name": "Item 01",
"layers": [
{
"name": "layer01",
},
{
"name": "layer02",
}
]
}
]
}
]
}
]
function addUniqueID(arr) {
arr.forEach((obj, i) => {
obj.parent = JSON.parse (`${i}`);
obj.id = JSON.parse(`${i}`);
obj.text =`${i}`;
if (obj.heading) {
addUniqueID(obj.heading);
}
// if (obj.layers) {
// addUniqueID(obj.layers);
// }
});
}
addUniqueID(treedata);
console.log(treedata);
CodePudding user response:
You have to use recursion and pass id as a parameter. Something like this:
let treedata = [
{
"heading": [
{
"name": "Heading 01",
"Items": [
{
"name": "Item 01",
"layers": [
{
"name": "layer01",
},
{
"name": "layer02",
}
]
}
]
}
]
}
]
function addUniqueID(arr, id) {
arr.forEach((obj, i) => {
obj.parent = id - 1;
obj.id = id;
if (obj.heading) {
addUniqueID(obj.heading, id 1);
}
if (obj.Items) {
addUniqueID(obj.Items, id 1);
}
if (obj.layers) {
addUniqueID(obj.layers, id 1);
}
});
}
addUniqueID(treedata, 1);
console.log(treedata);
CodePudding user response:
Here's an approach,
const data = [{ heading: [{name: "Heading 01", Items: [{name: "Item 01", layers: [{name: "layer01"}, { name: "layer02"}]}]}]}];
const addUniqueId = (arr, parentId) => {
const listKeys = ["heading", "Items", "layers"];
return arr.map((item, index) => {
const newId = parentId index 1;
const result = {
...item,
id: newId,
parent: parentId,
};
let droppable = false;
listKeys.forEach((key) => {
if (item[key]?.length) {
droppable = true;
result[key] = addUniqueId(item[key], newId);
}
});
return { ...result, droppable };
});
};
console.log(addUniqueId(data, 0));
CodePudding user response:
How about this recursion? passing parent
along the tree so that id would get proper value.
var data = [{
"heading": [{
"name": "Heading 01",
"Items": [{
"name": "Item 01",
"layers": [{
"name": "layer01",
},
{
"name": "layer02",
}
]
}]
}]
}]
const iterate = (obj, parent) => {
if (!obj) {
return;
}
parent = parent || 0;
var my_id = parent
Object.keys(obj).forEach(key => {
var value = obj[key]
if (typeof value === "object" && value !== null) {
if (!Array.isArray(value)) {
value.parent = parent;
value.id = my_id
value.droppable = true;
}
iterate(value, my_id)
}
})
}
iterate(data);
console.log(data);
.as-console-wrapper {
max-height: 100% !important;
}
CodePudding user response:
Pass the id as parameter to the function and increase by one in each depth.
let treedata = [
{
"heading": [
{
"name": "Heading 01",
"Items": [
{
"name": "Item 01",
"layers": [
{
"name": "layer01",
},
{
"name": "layer02",
}
]
}
]
}
]
}
];
function addUniqueID(arr, i) {
arr.forEach((obj) => {
obj.parent = i;
obj.id = i 1;
obj.text = i "";
obj.droppable = true;
if (obj.heading) {
addUniqueID(obj.heading, i 1);
}
else if (obj.layers) {
addUniqueID(obj.layers, i 1);
}
else if (obj.Items) {
addUniqueID(obj.Items, i 1);
} else {
obj.droppable = false;
}
});
}
addUniqueID(treedata, 0);
console.log(treedata);
CodePudding user response:
Anoter one recursive solution
const treedata = [{heading: [{name: "Heading 01",Items: [{name: "Item 01","layers": [{name: "layer01"},{name: "layer02"}]}]}]}];
const makeNextId = () => {
let count = 0;
return () => count = 1;
};
const nextId = makeNextId();
const iter = (arr, id, parent = 0) => arr.map((obj) => {
const arrayKeys = Object.keys(obj).filter((key) => Array.isArray(obj[key]));
const droppable = Boolean(arrayKeys.length);
return {
...obj,
id,
parent,
droppable,
...Object.fromEntries(arrayKeys.map((key) => [key, iter(obj[key], nextId(), id)] ))
}
});
const result = iter(treedata, nextId());
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }