am looking for a JSON tree from a plain JSON.
below is the Input and expected output json.
the input json doesnt have any order
There can be multiple items at each level and each item can have n number of childrens.
leafFlag = 0 means no children
leafFlag = 1 means has chidlren
path is the property which tells where the item will be placed
The expectedOutputJson needs to be placed in a table to display level wise data
var inputJson = [
{
"level": "1",
"leafFlag": "1",
"path":"p123",
"name":"food"
},
{
"level": "1",
"leafFlag": "1",
"path":"r125",
"name":"car"
},
{
"level": "2",
"leafFlag": "0",
"path":"p123/p345",
"name":"apple"
},
{
"level": "2",
"leafFlag": "1",
"path":"p123/p095",
"name":"banana"
},
{
"level": "3",
"leafFlag": "0",
"path":"p123/p095/p546",
"name":"grapes"
},
{
"level": "2",
"leafFlag": "1",
"path":"r125/yhes",
"name":"tata"
},
]
var expectedOutput = [
{
"level": "1",
"leafFlag": "1",
"path": "p123",
"name": "food",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "p123/p345",
"name": "apple"
},
{
"level": "2",
"leafFlag": "1",
"path": "p123/p095",
"name": "banana",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "p123/p095/p546",
"name": "grapes"
}
]
}
]
},
{
"level": "1",
"leafFlag": "1",
"path": "r125",
"name": "car",
"children": [
{
"level": "2",
"leafFlag": "1",
"path": "r125/yhes",
"name": "tata",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "r125/yhes/sdie",
"name": "Range Rover"
}
]
},
{
"level": "2",
"leafFlag": "0",
"path": "r125/theys",
"name": "suzuki"
}
]
}
]
i tried the below code but not able to proceed further
private prepareTreeStructure = (inputJson) => {
const treeFormat = (key, index, result) => {
if (key.indexOf('/') === -1) {
result = [...result, ...d[key]];
} else {
result.forEach((item, index) => {
let splitKeyArray = key.split('/');
splitKeyArray.forEach((splitItem, splitIndex) => {
if (splitKeyArray.indexOf(item.path) !== -1) {
if (!item['children']) {
item['children'] = [];
}
if (splitKeyArray.length === splitIndex + 1) {
result[index]['children'] = [...result[index]['children'], ...d[key]];
}
}
});
if (splitKeyArray.indexOf(item.path) !== -1) {
if (!result[index]['children']) {
result[index]['children'] = [];
}
result[index]['children'] = [...result[index]['children'], ...d[key]];
}
});
}
return result;
}
const d = inputJson.reduce((acc, ele) => {
if (!acc[ele.path]) {
acc[ele.path] = [];
}
acc[ele.path].push(ele);
return acc;
}, {});
console.log('dddd ', d);
this.result = [];
Object.keys(d).forEach((key, index) => {
this.result = treeFormat(key, index, this.result);
console.log('out ', this.result);
})
}
prepareTreeStructure(inputJson);
I think you're looking for something like this, works for an n number of levels:
var inputJson = [
{
"level": "1",
"leafFlag": "1",
"path":"p123",
"name":"food"
},
{
"level": "1",
"leafFlag": "1",
"path":"r125",
"name":"car"
},
{
"level": "2",
"leafFlag": "0",
"path":"p123/p345",
"name":"apple"
},
{
"level": "2",
"leafFlag": "1",
"path":"p123/p095",
"name":"banana"
},
{
"level": "3",
"leafFlag": "0",
"path":"p123/p095/p546",
"name":"grapes"
},
{
"level": "2",
"leafFlag": "1",
"path":"r125/yhes",
"name":"tata"
}
]
And the actual code:
var output = [];
inputJson = inputJson.sort((a, b) => (parseInt(a.level) > parseInt(b.level)) ? 1 : -1)
inputJson.forEach(v => {
if (v.level == "1") {
v.children = [];
output.push(v);
}
else {
pathValues = v.path.split("/");
pathValues.pop();
var node = null;
var fullPath = "";
pathValues.forEach(p => {
fullPath = fullPath === "" ? p : fullPath + "/" + p;
node = (node == null ? output : node.children).find(o => o.path === fullPath);
})
node.children = node.children || [];
node.children.push(v);
}
})
console.log(output)
See the jsfiddle: https://jsfiddle.net/L984bo6x/8/
var inputJson = [
{
"level": "1",
"leafFlag": "1",
"path":"p123",
"name":"food"
},
{
"level": "1",
"leafFlag": "1",
"path":"r125",
"name":"car"
},
{
"level": "2",
"leafFlag": "0",
"path":"p123/p345",
"name":"apple"
},
{
"level": "2",
"leafFlag": "1",
"path":"p123/p095",
"name":"banana"
},
{
"level": "3",
"leafFlag": "0",
"path":"p123/p095/p546",
"name":"grapes"
},
{
"level": "2",
"leafFlag": "0",
"path":"r125/yhes",
"name":"tata"
},
]
var expectedOutput = [
{
"level": "1",
"leafFlag": "1",
"path": "p123",
"name": "food",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "p123/p345",
"name": "apple"
},
{
"level": "2",
"leafFlag": "1",
"path": "p123/p095",
"name": "banana",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "p123/p095/p546",
"name": "grapes"
}
]
}
]
},
{
"level": "1",
"leafFlag": "1",
"path": "r125",
"name": "car",
"children": [
{
"level": "2",
"leafFlag": "1",
"path": "r125/yhes",
"name": "tata",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "r125/yhes/sdie",
"name": "Range Rover"
}
]
},
{
"level": "2",
"leafFlag": "0",
"path": "r125/theys",
"name": "suzuki"
}
]
}
]
const groupByLevels = inputJson => {
var levelsObj = {};
inputJson.forEach(ele => {
if (ele.level === "1") {
if (!levelsObj["1"]) {
levelsObj["1"] = [];
}
levelsObj["1"].push(ele)
} else {
if (!levelsObj[ele.level]) {
levelsObj[ele.level] = {};
}
var parKey = ele.path.substr(0, ele.path.lastIndexOf('/'));
if (!levelsObj[ele.level][parKey]) {
levelsObj[ele.level][parKey] = [];
}
levelsObj[ele.level][parKey].push(ele);
}
})
return levelsObj;
}
const mergeByGroups = (currLevelArr, groupJSON) => {
currLevelArr.forEach(ele => {
if (ele.leafFlag == "0") {
return ele;
}
let nextLevel = parseInt(ele.level) + 1 + ""
let nextLevelArr = groupJSON[nextLevel][ele.path];
mergeByGroups(nextLevelArr, groupJSON)
ele.children = nextLevelArr;
})
}
const constructOutput = groupJSON => {
mergeByGroups(groupJSON["1"], groupJSON);
return groupJSON["1"];
}
console.log(JSON.stringify(constructOutput(groupByLevels(inputJson)), null, 4));
Related
I have two arrays one is selectedOption and another is defaultOption, if the selectedOption id is present in any of the defaultOption array option property then it will be replaced with the current one . For an example i have added the expected_output
How could i achieve the expected output
let selectedOption = [
{
"count": 12,
"id": "16",
},
{
"count": 3,
"id": "4",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
]
let defaultOption = [
{
"item_select": {
"value": "16",
},
"options": []
},
{
"item_select": {
"value": "4",
},
"options": [
{
"value": "4"
},
{
"value": "5"
},
{
"value": "6"
},
{
"value": "7"
}
]
},
{
"item_select": {
"value": "8",
},
"options": [
{
"value": "8"
},
{
"value": "9"
},
{
"value": "10"
},
{
"value": "11"
}
]
},
{
"item_select": {
"value": "12",
},
"options": [
{
"value": "12"
},
{
"value": "13"
},
{
"value": "14"
},
{
"value": "15"
}
]
}
]
What I have tried so far
let expected_output = []
selectedOption.forEach(current => {
isDefaultOptionMatched = defaultOption.find(defOpt => defOpt.options.some(opt => opt.value === current.id))
if(isDefaultOptionMatched?.options){
let allMatches = selectedOption.filter(selOpt => {
defaultOption.some(defOption => defOption.options.find(dop => dop.value === selOpt.id))
})
expected_output.push(allMatches[allMatches.length - 1])
}else{
expected_output.push(current)
}
})
What I am getting is 6 elements instead of 5, and its not right.
expected output what I am looking
Instead of 6 objects of expected_output array it will be 5 objects because the second last object id => 6 is part of defaultOption[1].options. The element which got removed is.
{
"count": 3,
"id": "4",
},
Which is part of defaultOption[1].options
expected_output = [
{
"count": 12,
"id": "16",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
]
Any help is appreciated
Here's a semi-hacky approach (I don't like bucketing the items and remembering the order to rebuild the array later) but it works
let selectedOption = [
{
"count": 12,
"id": "16",
},
{
"count": 3,
"id": "4",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
];
let defaultOption = [
{
"item_select": {
"value": "16",
},
"options": []
},
{
"item_select": {
"value": "4",
},
"options": [
{
"value": "4"
},
{
"value": "5"
},
{
"value": "6"
},
{
"value": "7"
}
]
},
{
"item_select": {
"value": "8",
},
"options": [
{
"value": "8"
},
{
"value": "9"
},
{
"value": "10"
},
{
"value": "11"
}
]
},
{
"item_select": {
"value": "12",
},
"options": [
{
"value": "12"
},
{
"value": "13"
},
{
"value": "14"
},
{
"value": "15"
}
]
}
];
const result =
selectedOption.reduce((acc, el, order) => {
// bucket each element based on where it's found in defaultOption
const def = defaultOption.find(el2 => el2.options.some(el3 => el3.value === el.id));
if (def) {
const defId = def.item_select.value;
acc[defId] = {...el, order};
} else {
acc[el.id] = {...el, order};
}
return acc;
}, {});
// fix the order and remove the order field
const finish = Object.values(result).sort((a, b) => a.order - b.order).map(({order, ...rest}) => rest);
console.log(finish);
let selectedOption = [
{
"count": 12,
"id": "16",
},
{
"count": 3,
"id": "4",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
]
let defaultOption = [
{
"item_select": {
"value": "16",
},
"options": []
},
{
"item_select": {
"value": "4",
},
"options": [
{
"value": "4"
},
{
"value": "5"
},
{
"value": "6"
},
{
"value": "7"
}
]
},
{
"item_select": {
"value": "8",
},
"options": [
{
"value": "8"
},
{
"value": "9"
},
{
"value": "10"
},
{
"value": "11"
}
]
},
{
"item_select": {
"value": "12",
},
"options": [
{
"value": "12"
},
{
"value": "13"
},
{
"value": "14"
},
{
"value": "15"
}
]
}
]
let expected_output = []
defaultOption.forEach(defOption => {
let allMatches = selectedOption.filter(selOpt => defOption.options.find(dop => dop.value === selOpt.id))
if(allMatches.length > 0){
expected_output.push(allMatches[allMatches.length - 1])
}
})
selectedOption.forEach(selOpt => {
let isDefaultOptionMatched = defaultOption.find(defOpt => defOpt.options.some(opt => opt.value === selOpt.id))
if(!isDefaultOptionMatched){
expected_output.push(selOpt)
}
})
console.log(expected_output)
Sample Input:
[
{
"id": "p1",
"top": 130,
"left": 298,
"Key": "test1",
"Next": "special"
},
{
"id": "p2",
"Key": "special",
"specialkey": [
{"key": "1", "value": "p3"},
{"key": "0", "value": "p4"},
{"key": "2", "value": "p5"}
],
"Next": "",
"RepeatText": "p8",
"RepeatTextNew": "p9",
},
{
"id": "p3",
"user": "aa",
"Key": "test3",
"Text": "hi"
},
{
"id": "p4",
"Key": "special",
"specialkey": [
{"key": "1", "value": "p6"},
{"key": "0", "value": "p7"}
]
},
{
"id": "p5",
"user": "aa",
"Key": "test5",
"Text": "hi"
},
{
"id": "p6",
"user": "aa",
"Key": "test6",
"Text": "hi"
},
{
"id": "p7",
"user": "aa",
"Key": "test7",
"Text": "hi"
},
{
"id": "p8",
"user": "aa",
"Key": "test8",
"Text": "hi"
},
{
"id": "p9",
"user": "aa",
"Key": "test9",
"Text": "hi"
}
]
Sample Output:
{
"test1": {
"id": "p1",
"top": 130,
"left": 298,
"Key": "test1",
"Next": {
"special": {
"id": "p2",
"Key": "special",
"Next": "",
"RepeatText": {
"p8": {
"id": "p8",
"user": "aa",
"Key": "test8",
"Text": "hi"
}
},
"RepeatTextNew": {
"p9": {
"id": "p9",
"user": "aa",
"Key": "test9",
"Text": "hi"
}
},
"specialkey": [
{
"key": "1",
"value": {
"id": "p3",
"user": "aa",
"Key": "test3",
"Text": "hi"
}
},
{
"key": "0",
"value": {
"id": "p4",
"Key": "special",
"specialkey": [
{
"key": "1",
"value": {
"id": "p6",
"user": "aa",
"Key": "test6",
"Text": "hi"
}
},
{
"key": "0",
"value": {
"id": "p7",
"user": "aa",
"Key": "test7",
"Text": "hi"
}
}
]
}
},
{
"key": "2",
"value": {
"id": "p5",
"user": "aa",
"Key": "test5",
"Text": "hi"
}
}
]
}
}
}
}
When the key is equal to special it can have a nested structure and for either we just need to match with the next key
With the below code, I am not able to achieve the expected output.
const processObject = ({ Next, ...rest }) => {
const result = { ...rest };
if (formatData.find((y) => y.Key == 'special')) {
const nextObject = formatData.find((y) => y.Key == 'special')
if (nextObject.specialkey) {
for (let i = 0; i < nextObject.specialkey.length; i++) {
let currentObject = formatData.find((y) => y.id === nextObject.specialkey[i].value)
nextObject.specialkey[i].value = currentObject
}
result.Next = {
[nextObject.Key]: processObject(nextObject),
};
}
}
if (Next) {
const nextObject = formatData.find((y) => y.id === Next);
result.Next = {
[nextObject.Key]: processObject(nextObject),
};
}
return result;
};
const response = {
[formatData[0].Key]: processObject(formatData[0]),
};
return response
Is this what you're after?
const input = [
{
"id": "p1", "top": 130, "left" :298, "Key": "test1",
// I've changed this from "special" to "p2"
"Next": "p2"
// rest of input is the same...
},{"id":"p2","Key":"special","specialkey":[{"key":"1","value":"p3"},{"key":"0","value":"p4"},{"key":"2","value":"p5"}],"Next":"","RepeatText": "p8","RepeatTextNew":"p9"},{"id":"p3","user":"aa","Key":"test3","Text":"hi"},{"id":"p4","Key":"special","specialkey":[{"key":"1","value":"p6"},{"key":"0","value":"p7"}]},{"id":"p5","user":"aa","Key":"test5","Text":"hi"},{"id":"p6","user":"aa","Key":"test6","Text":"hi"},{"id":"p7","user":"aa","Key":"test7","Text":"hi"},{"id":"p8","user":"aa","Key":"test8","Text":"hi"},{"id":"p9","user":"aa","Key":"test9","Text": "hi"}];
// Gets an object by its id
const getById = id => input.find(x => x.id === id);
const processObject = ({ Next, specialkey, RepeatText, RepeatTextNew, ...rest }) => {
let processedNext;
if (Next) {
const nextObject = getById(Next);
processedNext = { [nextObject.Key]: processObject(nextObject) };
}
return {
...rest,
// This spread syntax means we don't add the Next or
// specialkey property if it isn't present in the input
// object
...processedNext ? { Next: processedNext } : {},
...RepeatText
? { RepeatText: { [RepeatText]: processObject(getById(RepeatText)) } }
: {},
...RepeatTextNew
? { RepeatTextNew: { [RepeatTextNew]: processObject(getById(RepeatTextNew)) } }
: {},
...specialkey
? {
specialkey: specialkey.map(({ key, value }) => ({
key,
value: processObject(getById(value))
}))
}
: {}
};
}
console.log(processObject(input[0]));
In your code, you seem to be looking up objects by their id, so that's why I changed the first object input's Next from "special" (the Key of the p2 object) to "p2".
The Overall Context is to find the leaf node of every parent(x) and children(x1) if there are more than 2 leaf nodes make them the child's as one under another
I Tried to use loadash in Nodejs but I was unable to get the expected result
I have a JSON Data
{
"Id": "1",
"name": "x",
"parent": "",
"children": [{
"Id": "2",
"name": "x1",
"parent": "1",
"children": [{
"Id": "3",
"name": "x2",
"parent": "2"
}, {
"Id": "4",
"name": "x3",
"parent": "2"
},
{
"Id": "5",
"name": "x4",
"parent": "2"
},
{
"Id": "6",
"name": "x5",
"parent": "2"
},
{
"Id": "7",
"name": "x6",
"parent": "2"
},
{
"Id": "8",
"name": "x7",
"parent": "2"
}
]
},
{
"Id": "9",
"name": "x8",
"parent": "1"
},
{
"Id": "10",
"name": "x10",
"parent": "1"
}, {
"Id": "11",
"name": "x9",
"parent": "1"
},
{
"Id": "12",
"name": "x11",
"parent": "1"
}
]
}
I would like to change into the below format
{
"Id": "1",
"name": "x",
"parent": "",
"children": [{
"Id": "2",
"name": "x1",
"parent": "1",
"children": [{
"Id": "3",
"name": "x2",
"IC": "Yes",
"parent": "2",
"children": [{
"Id": "5",
"name": "x4",
"IC": "Yes",
"parent": "2",
"children": [{
"Id": "7",
"parent": "2",
"name": "x6"
}]
}]
},
{
"Id": "4",
"name": "x3",
"IC": "Yes",
"parent": "2",
"children": [{
"Id": "5",
"name": "x5",
"IC": "Yes",
"parent": "2",
"children": [{
"Id": "7",
"name": "x7",
"IC": "Yes",
"parent": "2"
}]
}]
}
]
},
{
"Id": "9",
"name": "x8",
"parent": "1",
"children": [{
"Id": "10",
"name": "x10",
"IC": "Yes",
"parent": "1"
}]
},
{
"Id": "11",
"name": "x9",
"parent": "1",
"children": [{
"Id": "11",
"name": "x11",
"parent": "1",
"IC": "Yes"
}]
}
]
}
Note:
1. If there are 8 leaf nodes it should be split 4+4,
2. If there are 9 leaf nodes it should be split 5+4,
3. In the same way, If it has 13 it can be split into 7+6.
any help would be appreciated
thanks in advance
The following code will take all leaf nodes and create 2 even branches from them. The output is not identical to yours, but you mention in your comments that the branches can be built randomly from the leaf nodes, and this code respects that requirement.
const input = {
"name": "x",
"children": [
{
"name": "x1",
"children": [
{
"name": "x2"
},
{
"name": "x3"
},
{
"name": "x4"
},
{
"name": "x5"
},
{
"name": "x6"
},
{
"name": "x7"
}
]
},
{
"name": "x8"
},
{
"name": "x10"
},
{
"name": "x9"
},
{
"name": "x11"
}
]
};
function cutLeafNodes(node){
if(!node.children){
return;
}
const leaves = [];
const branches = [];
node.children.forEach(child => {
if(child.children){
branches.push(child);
} else {
leaves.push(child);
}
});
node.children = branches;
return leaves;
}
function reorderLeaves(nodes){
if(!nodes){
return;
}
const midpoint = nodes.length / 2;
const newChildren = [];
newChildren.push(createAncestry(nodes.splice(0, midpoint)));
newChildren.push(createAncestry(nodes));
return newChildren;
}
function createAncestry(nodes){
let currentChild = nodes[0];
const firstChild = currentChild;
for (let i = 1; i < nodes.length; i++) {
currentChild.children = [nodes[i]];
currentChild = currentChild.children[0];
}
return firstChild;
}
function reorganizeTree(node){
const leaves = cutLeafNodes(node);
if(node.children){
node.children.forEach(child => {
reorganizeTree(child);
});
}
if(leaves){
const newBranches = reorderLeaves(leaves);
newBranches.forEach(branch =>{
node.children.push(branch);
})
}
return node;
}
const output = reorganizeTree(input);
console.debug(output);
I want to write a function that will find the Categoy[3].options[3].label and matches it to the letter "D".
How do I iterate through the nested objects below to go through the TagCategory.options and search for the option that matches to the letter "D"? If it matches the letter "D", it should return true.
"Category":
[
{
"field": "A",
"options": [
{"tag": "100", "value": "yes"}
],
"label": "Red"
},
{
"field": "tanks",
"type": true,
"options": [
{"tag_value": "4", "value": "4", "label": "A"},
{"tag_value": "3", "value": "3", "label": "B"},
{"tag_value": "2", "value": "2", "label": "C"},
{"tag_value": "1", "value": "1", "label": "D"},
{"tag_value": "5", "value": "5", "label": "E"}
],
"label": "Tanks"
}
]
Something like this?
function findLabel(arr, label) {
for (var i in arr) {
const options = arr[i].options;
const find = options.find(o => o.label == label);
if (find) {
return true;
}
}
return false;
}
const test = findLabel(Category, "D");
Category is your array
function check(category, letter){
var obj;
var optionObj;
for(var i = 0; i < category.length; i++){
obj = Category[i];
options = obj.options;
for(var j = 0; j < options.length; j++){
optionObj = option[j];
if(optionObj.label === letter) return true;
}
}
return false;
}
Here is a rough example of what I mean by a nested for loop.
category = {...}; // your object above
for (i in category) {
field = category[i];
for (option_i in field.options) {
// This is the nested for loop - called thus because it's inside one.
if (field.options[option_i].label == "D"){
return true;
}
}
}
You can use Array.prototype.some()
let optionHasLabelDBool = obj.Category.some(({options}) =>
options.some(({label}) => label === "D"));
let obj = {
"Category":
[{
"field": "A",
"options": [{
"tag": "100",
"value": "yes"
}],
"label": "Red"
},
{
"field": "tanks",
"type": true,
"options": [{
"tag_value": "4",
"value": "4",
"label": "A"
}, {
"tag_value": "3",
"value": "3",
"label": "B"
}, {
"tag_value": "2",
"value": "2",
"label": "C"
}, {
"tag_value": "1",
"value": "1",
"label": "D"
}, {
"tag_value": "5",
"value": "5",
"label": "E"
}],
"label": "Tanks"
}
]
};
let optionHasLabelD = obj.Category.some(({options}) => options.some(({label}) => label === "D"));
console.log(optionHasLabelD);
Using a function, without arrow function or object destructing
function checkOption(array, prop, key, value) {
return array.some(function(obj) {
return obj[prop].some(function(match) {
return match[key] === value;
});
});
}
let optionHasLabelDBool = checkOption(obj.Category, "options", "label", "D");
let obj = {
"Category": [{
"field": "A",
"options": [{
"tag": "100",
"value": "yes"
}],
"label": "Red"
},
{
"field": "tanks",
"type": true,
"options": [{
"tag_value": "4",
"value": "4",
"label": "A"
}, {
"tag_value": "3",
"value": "3",
"label": "B"
}, {
"tag_value": "2",
"value": "2",
"label": "C"
}, {
"tag_value": "1",
"value": "1",
"label": "D"
}, {
"tag_value": "5",
"value": "5",
"label": "E"
}],
"label": "Tanks"
}
]
};
function checkOption(array, prop, key, value) {
return array.some(function(obj) {
return obj[prop].some(function(match) {
console.log(match[key], value, match[key] === value);
return match[key] === value;
});
});
}
let optionHasLabelDBool = checkOption(obj.Category, "options", "label", "D");
console.log(optionHasLabelDBool);
I can't figure out why this tree 'flattener' is returning only innermost children, the expectation is that it should return flattened tree.
var x = {
"Fields": {
"Id": "1",
"MasterAccountId": "",
"ParentAccountId": "",
"Name": "Name 1"
},
"Children": [{
"Fields": {
"Id": "2",
"MasterAccountId": "1",
"ParentAccountId": "1",
"Name": "Name 2"
},
"Children": [{
"Fields": {
"Id": "5",
"MasterAccountId": "1",
"ParentAccountId": "2",
"Name": "Name 5"
},
"Children": [{
"Fields": {
"Id": "6",
"MasterAccountId": "1",
"ParentAccountId": "5",
"Name": "Name 6"
}
}, {
"Fields": {
"Id": "7",
"MasterAccountId": "1",
"ParentAccountId": "5",
"Name": "Name 7"
}
}]
}]
}]
}
function recurs(n) {
console.log(n.Fields.Name);
return (n.Children != undefined ? $.map(n.Children, recurs) : n);
}
var r = recurs(x);
It returns elements with id 6, 7, while console.logs all 5 of them.
http://plnkr.co/edit/LdHiR86EDBnZFAh6aAlG?p=preview
Your function only returns n if n.Children is undefined. Since you want a flat array with all the objects you have to build one.
function recurs(n) {
var out = [];
out.push(n.Fields);
if (n.Children) {
for (var i=0, c; c = n.Children[i]; i++) {
out.push.apply(out, recurs(c));
}
}
return out;
}