我正在尝试使用一些新值(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;
};
答案 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;
};