在多维数组javascript中为节点赋值

时间:2011-05-14 11:38:03

标签: javascript json multidimensional-array

我正在尝试使用一些新值(text / object / array)在json对象中分配一个元素。我有一个交换函数,它接受json对象,一个带索引的数组,用于检索元素和用它替换它的值。目前我正在使用eval,其中一些是“邪恶的”。有没有更好的方法来做这个没有eval或在这种情况下eval ok?请记住,它必须是动态的,因为阵列可能会发生变化。另外值得注意的是,我是以编程方式创建数组参数。

//array looks like: ["cluster", "2", "segment", "0", "node", "3"]    
JsonManager.prototype.swap = function(json, array, val){
        var statement = "json";
        for (var i = 0; i < array.length; i++) {
            if(!isNumeric(array[i]))
            {
            statement += "[\"" + array[i] + "\"]";          
            }else{
                statement += "[" + array[i] + "]"   
            }
        }
        statement += " = val";
        eval(statement);
    };

示例JSON对象:

var customers = {
    "cluster": [{
        "clusterid": "cluster1.1",
        "color": "blue",
        "flights": "784",
        "profit": "524125",
        "clv": "2364",
        "segment": [{
            "segmentid": "segment1.1",
            "color": "green",
            "flights": "82",
            "profit": "22150",
            "clv": "1564",
            "node": [{
                "nodeid": "node1.1",
                "color": "orange",
                "xpos": "1",
                "ypos": "1"
            }, {
                "nodeid": "node1.2",
                "color": "blue",
                "xpos": "1",
                "ypos": "2"
            }, {
                "nodeid": "node1.3",
                "color": "orange",
                "xpos": "1",
                "ypos": "3"
            }, {
                "nodeid": "node1.4",
                "color": "orange",
                "xpos": "1",
                "ypos": "4"
            }]
        }, {
            "segmentid": "segment1.2",
            "color": "red",
            "flights": "2",
            "profit": "2150",
            "clv": "1564",
            "node": [{
                "nodeid": "node2.1",
                "color": "tan",
                "xpos": "2",
                "ypos": "1"
            }, {
                "nodeid": "node2.2",
                "color": "tan",
                "xpos": "2",
                "ypos": "2"
            }, {
                "nodeid": "node2.3",
                "color": "tan",
                "xpos": "2",
                "ypos": "3"
            }, {
                "nodeid": "node2.4",
                "color": "tan",
                "xpos": "2",
                "ypos": "4"
            }]
        }]
    }, {
        "clusterid": "cluster1.2",
        "flights": "4",
        "profit": "5245",
        "clv": "2364",
        "segment": [{
            "segmentid": "segment1.2",
            "flights": "2",
            "profit": "2150",
            "clv": "1564",
            "node": [{
                "nodeid": "node3.1",
                "xpos": "3",
                "ypos": "1"
            }, {
                "nodeid": "node3.2",
                "xpos": "3",
                "ypos": "2"
            }, {
                "nodeid": "node3.3",
                "xpos": "3",
                "ypos": "3"
            }, {
                "nodeid": "node3.4",
                "xpos": "3",
                "ypos": "4"
            }]
        }]
    }, {
        "clusterid": "cluster1.3",
        "flights": "10",
        "profit": "456978",
        "clv": "548",
        "segment": [{
            "segmentid": "segment1.3",
            "flights": "2",
            "profit": "2150",
            "clv": "1564",
            "node": [{
                "nodeid": "node4.1",
                "xpos": "4",
                "ypos": "1"
            }, {
                "nodeid": "node4.2",
                "xpos": "4",
                "ypos": "2"
            }, {
                "nodeid": "node4.3",
                "xpos": "4",
                "ypos": "3"
            }, {
                "nodeid": "node4.4",
                "xpos": "4",
                "ypos": "7"
            }]
        }]
    }]
};

这是我的测试方法:

JsonManager.prototype.init = function(){
    var clause = new Clause("nodeid", "node4.4");
    var indexes = this.search(customers, clause);
    this.swap(customers, indexes.reverse(), {"name": "kevin"});
    var test = customers["cluster"][2]["segment"][0]["node"][3];  //hard coded pointer to node4.4
    var breakPoint = "breakpoint";  //Just used as a point to stop the debugger to see test
};

此处未来的参考是进一步评论的解决方案:

JsonManager.prototype.swap = function(obj, path, value) {

   //This is the inner function we are recursing into 
   function descend(obj, path) {
    /*This if statement is used to stop the recrusion,
    when we have iterated through all the paths, it returns
    the object above our desired object */
        if (path.length == 0) {
            return obj;
        }
    /*Recurse into the function passing in the top level object and remove
    the top level object from our path*/ 
        return descend(obj[path[0]], path.slice(1));
    }
//Pass in the object and the (path - the last element)
    var node = descend(obj, path.slice(0, -1));
//Get the last node in path, pull it from node and assign the value
    node[path[path.length - 1]] = value;
};

2 个答案:

答案 0 :(得分:1)

您的“JSON”对象只是一个JavaScript对象。更重要的是,它是一棵树,树最容易使用递归遍历。

JsonManager.prototype.swap = function(obj, path, value) {
    function descend(obj, path) {
        if (path.length == 0) {
            return obj;
        }
        return descend(obj[path[0]], path.slice(1));
    }

    var node = descend(obj, path.slice(0, -1));
    node[path[path.length - 1]] = value;
};

slice将从数组中取出一个块。因此path.slice(1)返回path而没有第一个元素,path.slice(0, -1)返回它而没有最后一个元素。这意味着我们descend到对象的倒数第二个节点,然后使用正常的数组表示法设置最后一个节点。了解它的最简单方法是在纸上手动完成它,例如你上面的例子。

答案 1 :(得分:1)

没有理由使用eval,只需将对象分配给变量,并使用该变量进入每个级别:

JsonManager.prototype.swap = function(json, array, val){
  var j = json;
  for (var i = 0; i < array.length - 1; i++) {
    j = j[array[i]];
  }
  j[array[array.length - 1]] = val;
};