views:

110

answers:

2

Hi,

I have a JSON tree that contains nodes and children - the format is:

jsonObject = 
{
  id:nodeid_1,
  children: [
  {
    id:nodeid_2,
    children:[]
  },
  {
    id:nodeid_3,
    children:[
    {
      id:nodeid_4,
      children:[]
    },
    {
      id:nodeid_5,
      children:[]
    }
  }
}

I don't know the depth of this tree, a node is capable of having many children that also have many children and so on.

My problem is that I need to add nodes into this tree by using a nodeID. For example, a function that can take a nodeID and the node object (including its children), would be able to replace that node within the tree - which as a result would become a bigger tree.

I have only come across recursive functions that allow me to traverse all the nodes within a JSON tree and a modification I have made of one of these functions returns me the node object - but doesn't help me as I need to modify the original tree:

var findNode = {
node:{},
find:function(nodeID,jsonObj) {
    if( typeof jsonObj == "object" ) {
        $.each(jsonObj, function(k,v) {
            if(v == nodeID) {
                findNode.node = $(jsonObj).eq(0).toArray()[0];        
            } else {
                findNode.find(nodeID,v); 
            }
        });
    } else {
        //console.log("jsobObj is not an object");
    }
  }
}

which allows me to do the following test:

findNode.find("nodeid_3",json);
alert(findNode.node);

So to sum up - how can I modify a value of a JSON tree that has an unknown depth?

Thanks in advance

A: 

If you want to modify a node, like you said, you can just modify the properties of that node.

var node = findNode.find("nodeid_3",json);
node.id = "nodeid_3_modified";
node.children = [];

Also, why are you using jQuery for this?

Here's an alternative without using jQuery should work:

function findNode(object, nodeId) {
   if (object.id === nodeId) return object;

   var result;
   for (var i = 0; i < object.children.length; i++) {
      result = findNode(object.children[i], nodeId);
      if (result !== undefined) return result;
   }
}
CD Sanchez
@Daniel: [`jQuery.each`](http://api.jquery.com/jQuery.each/) (aka `$.each`) is a utility function, basically a convenience wrapper for `for..in` when you apply it to objects that aren't arrays. Totally different thing from the [`each`](http://api.jquery.com/each/) method of jQuery *instances*. If the OP is using jQuery for something else, no harm in using the convenience function as well (other than all the function calls involved).
T.J. Crowder
@T.J. Crowder: Yep. But why is he converting `jsObj` to a jQuery object? jQuery collections and methods are typically meant for DOM Elements -- there must be a better way.
CD Sanchez
I've just found out that all the variables I'm using are pointers to the JSON tree - so findNode.node is actually the node within the tree!
Dan Smith
A: 

That is not JSON, it is a Javascript object literal. JSON is a certain way to encode a simple Javascript object into a string; your example is not written that way. Also, your code does not manipulate JSON objects (which are actually strings, not objects); it manipulates Javascript objects (which is a way simpler task).

That said, I'm not sure what your actual question is, but if it's about adding new elements to the children array, you can use Array.push:

findNode.find("nodeid_3",json);
findNode.node.children.push(child);

(This assumes that findNode.find actually works, which I'm pretty sure it does not.)

Tgr
findNode.find() does work, and I've just used your suggestion of using .children.push(child) - which has successfully modified my JSON tree. thanks
Dan Smith