How to modify nth nested object property?

Viewed 38

Here's the original object data.

{
  "name": "animals",
  "children": [
    { "name": "mammals" },
    {
      "name": "reptile",
      "children": [
        { "name": "tortoise" },
        { "name": "snake", "children": [{ "name": "lizard" }] }
      ]
    },
    { "name": "birds" }
  ]
}

I have to add a new value to any children.

Provided arguments:

pathArrary : like ['animals', 'reptile', 'snake']
value: 'water snake'

Then water snake should be added as the last children of snake.

Target Object:

{
  "name": "animals",
  "children": [
    { "name": "mammals" },
    {
      "name": "reptile",
      "children": [
        { "name": "tortoise" },
        {
          "name": "snake",
          "children": [
            { "name": "lizard" }]
            { "name": "water snake" }
          ]
        }
      ]
    },
    { "name": "birds" }
  ]
}

Any help would be appreciated. Thanks.

2 Answers

Here's the solution to the above question.

const addNewPropToObj = (obj, path, value, depth) => {
  const hasChildren = "children" in obj;

  if (!hasChildren) {
    return {
      ...obj,
      children: [{ name: value }],
    };
  }

  let children = obj.children;
  const activeIdx = children.findIndex(
    (item) => item.name === path[path.length - depth]
  );

  if (depth > 0)
    children[activeIdx] = addNewPropToObj(
      children[activeIdx],
      path.slice(1),
      value,
      depth - 1
    );
  else children = [...children, { name: value }];

  return {
    ...obj,
    children,
  };
};

Here is another take on it:

const data={
  "name": "animals",
  "children": [
{ "name": "mammals" },
{
  "name": "reptile",
  "children": [
    {

 "name": "tortoise" },
    { "name": "snake", "children": [{ "name": "lizard" }] }
  ]
},
{ "name": "birds" }
  ]
},
 trgt=['animals','reptile','snake'],
 val='water snake';

function get(obj,keys){
  const ob=obj?.children.find(v=>v.name==keys[0]??"");
  if(ob&&keys.length>1) return get(ob,keys.slice(1));
  else return ob;
}

console.log(get({children:[data]},trgt)?.children.push({name:"water snake"})?"success:":"failure:",data);

The conditional chain expression ?.children in the script helps to avoid throwing an error in case of certain parts of the address path not being found. They will then return an undefined value which can be used to make further decisions, like abandoning the search itself or returning a "failure" message when trying to add another value to it.

Related