1

I need to add key value pair at the end of the tree like json object.

[{
    "name": "minpur",
    "children": [{
        "name": "ppp1",
        "children": [{
            "name": "feeder",
            "children": [{
                "name": "rmu16",
                "children": [{
                    "name": "invt16",
                    "children": [{
                        "aname": "inv 01"
                    }]
                }]
            }]
        }]
    }]
}]

Expected

[{
  "name": "minpur",
  "children": [{
    "name": "ppp1",
    "children": [{
      "name": "feeder",
      "children": [{
        "name": "rmu16",
        "children": [{
          "name": "invt16",
          "children": [{
            "aname": "inv 01",
            **
            "value": 300 **
          }]
        }]
      }]
    }]
  }]
}]

tried recursive function as below

let traverse = function(jsonObj) {
  if (jsonObj !== null && typeof jsonObj == "object") {
    return Object.entries(jsonObj).forEach(([key, value]) => {
      if (key != "aname") {
        traverse(value);
      } else {
        return value;
      }
    });
  }
}
0

4 Answers 4

1

Check if the aname key exists on the object, and add the property if it does. If it doesn't iterate the children with Array.forEach(), and calls traverse on the children.

const traverse = (key, value) => obj => {
  const inner = obj => {
    if(obj.hasOwnProperty(key)) obj.value = value
    else obj.children.forEach(inner)
  }
  
  return inner(obj)
}

const tree = [{"name":"minpur","children":[{"name":"ppp1","children":[{"name":"feeder","children":[{"name":"rmu16","children":[{"name":"invt16","children":[{"aname":"inv 01"}]}]}]}]}]}]

tree.forEach(traverse('aname', 300))

console.log(tree)

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

2 Comments

Hi, thanks for the help, how can we make value dynamic, i.e inside the loop and add the values dynamically
I've updated the function to accept and key to search, and a value to set.
0

Here is a more functional solution where the original values are not changed. The children are inspected and if there is no children, the passed keys are used to extend the current node.

const obj = [{
  "name": "minpur",
  "children": [{
    "name": "ppp1",
    "children": [{
      "name": "feeder",
      "children": [{
        "name": "rmu16",
        "children": [{
          "name": "invt16",
          "children": [{
            "aname": "inv 01"
          }]
        }]
      }]
    }]
  }]
}]

function addToLeaf(append, node) {
  if (!node.children) {
    return {
      ...node,
      ...append
    }
  }
  return { 
    ...node,
    ...{ children: node.children.map(child => addToLeaf(append, child))}
  }
}

const result = obj.map((node) => addToLeaf({
  value: 300
}, node));

console.log(result);

2 Comments

Hi , thanks for the help. this doesn't work if the value field is a dynamic value which is inside the loop.
Why not? You could pass in a function generating the value into the loop.
0

If you want to use JS utility library lodash it gives you many methods to handle such complex structures.

For this I would suggest _.set - https://lodash.com/docs/4.17.11#set

const _u = _.noConflict(); 
var object = { 'a': [{ 'b': { 'c': 3 } }] };
 
_u.set(object, 'a[0].b.c', 4);
console.log(object);
// => 4
 
_u.set(object, ['x', '0', 'y', 'z'], 5);
console.log(object);
// => 5
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Comments

0

You can create a recursive function which traverses arrays of objects and merges a found object (by specified key name) with a specified by you argument. No lodash needed:

let data = [{ "name": "minpur", "children": [{ "name": "ppp1", "children": [{ "name": "feeder", "children": [{ "name": "rmu16", "children": [{ "name": "invt16", "children": [{ "aname": "inv 01" }] }] }] }] }] }]

let deepSetByKey = (a, k, setObj) =>
  a.forEach(o => k in o ? Object.assign(o, setObj) : 
   'children' in o ? deepSetByKey(o.children, k, setObj) : 0) && a

deepSetByKey(data, 'aname', { value: 300 }) // call the fn

console.log(data[0].children[0].children[0].children[0].children[0].children[0])

The idea is to recursively traverse with Array.forEach and use Object.assign when you find the prop you are looking for in the current object.

2 Comments

i have one doubt , how can we make the value dynamic instead of static value = 300, can we have something like value=data[i] ?
What is data[i]? Can you update your question above so there is a clear requirement of what and how it should work? You can simply change the setObj to whatever you want as it is now.

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.