0

I have the following piece of json, it follows a specific pattern but each object can have any number of children and each of those children objects can have any number of children ..

[
  {
    "name": "1st level",
    "parentId": "",
    "id": "dummyvalue1",
    "children": [
      {
        "name": "2nd level child",
        "parentId": "dummyvalue1",
        "id": "dummyvalue2"
      },
      {
        "name": "another 2nd level child",
        "id": "dummyvalue3",
        "children": [
          {
            "name": "3rd level child",
            "id": "dummyvalue4",
            "children": [
              {
                "name": "4th level child",
                "parentId": "dummyvalue4",
                "id": "dummyvalue5"
              }
            ],
            "parentId": "dummyvalue3"
          }
        ],
        "parentId": "dummyvalue1"
      }
    ]
  }
]

The problem is, I only need to access objects at a specific depth within this nested object/array structure.

And that depth is dynamic.

If the depth equals 3, then I would like to add a new dummy object into the children array for that level. So the new structure would look like this ..

[
  {
    "name": "1st level",
    "parentId": "",
    "id": "dummyvalue1",
    "children": [
      {
        "name": "2nd level child",
        "parentId": "dummyvalue1",
        "id": "dummyvalue2"
      },
      {
        "name": "another 2nd level child",
        "id": "dummyvalue3",
        "children": [
          {
            "name": "3rd level child",
            "id": "dummyvalue4",
            "children": [
              {
                "name": "4th level child",
                "parentId": "dummyvalue4",
                "id": "dummyvalue5"
              }
            ],
            "parentId": "dummyvalue3"
          },
          {
            "name": "NEW OBJECT",
            "parentId": "dummyvalue3",
            "id": "random"
          }
        ],
        "parentId": "dummyvalue1"
      }
    ]
  }
]

Is there a clean way to do this? Instead of huge loops trying to iterate to the right level. Also dont think I can use dot notation since the number of levels and the depth variable is dynamic

2
  • 1
    what if in your object "name": "2nd level child" there is a children property, and that path also contain 3rd level depth? you want to push the new object in both the path at level 3? Commented Jul 19, 2017 at 21:00
  • no, i would like to specify which 3rd level children to insert using dummyvalue4 as an identifier for the parent Commented Jul 19, 2017 at 21:57

1 Answer 1

1

I've created this function:

function addChild(currentChild, childToAdd, depth) {
  if (depth === 1) {
    currentChild.children.push(childToAdd);
    return;
  }

  const nextChild = currentChild.children.filter(child => child.children && child.children.length)[0];

  if (!nextChild) {
     if (currentChild.children && currentChild.children.length) {
       currentChild.children[0].children = [childToAdd];
     } else {
       currentChild.children = [childToAdd];
     }
     return;
  }

  addChild(nextChild, childToAdd, depth - 1);
}

It takes 3 arguments:

  1. The current child
  2. The child to add
  3. The remaining depth to run through

If the depth is 1, it simply add the child to the children. If not, it looks inside the children, take the first one with children and make a recursive call to the same function.

const data = [
  {
    "name": "1st level",
    "parentId": "",
    "id": "dummyvalue1",
    "children": [
      {
        "name": "2nd level child",
        "parentId": "dummyvalue1",
        "id": "dummyvalue2"
      },
      {
        "name": "another 2nd level child",
        "id": "dummyvalue3",
        "children": [
          {
            "name": "3rd level child",
            "id": "dummyvalue4",
            "children": [
              {
                "name": "4th level child",
                "parentId": "dummyvalue4",
                "id": "dummyvalue5"
              }
            ],
            "parentId": "dummyvalue3"
          }
        ],
        "parentId": "dummyvalue1"
      }
    ]
  }
]

function addChild(currentChild, childToAdd, depth) {
  if (depth === 1) {
    currentChild.children.push(childToAdd);
    return;
  }
  
  const nextChild = currentChild.children.filter(child => child.children && child.children.length)[0];
  
  if (!nextChild) {
     if (currentChild.children && currentChild.children.length) {
       currentChild.children[0].children = [childToAdd];
     } else {
       currentChild.children = [childToAdd];
     }
     return;
  }

  addChild(nextChild, childToAdd, depth - 1);
}

addChild(data[0], {foo: 'bar'}, 3);
addChild(data[0], {bar: 'baz'}, 2);
addChild(data[0], {baz: 'foo'}, 1);
addChild(data[0], {extraChild: 'foo'}, 4);


console.log(data);

Sign up to request clarification or add additional context in comments.

5 Comments

It's important to note this will always add to the children of the first element of the matching depth.
Yes, I've mentioned it above the snippet.
what does this function do if I specify depth of 2 and the existing data structure only has 1 level of depth? i.e the children array at level 1 does not exist .. is it possible to create it at that point?
@bobbyrne01 I've updated my code so it adds a child to the children at the maximum depth provided if the initial depth is greater than the maximal depth of the object.
@bobbyrne01 if it's ok for you, feel free top upvote and accept my answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.