尝试理解JavaScript并写入对象。我有一个对象:
{
"name":"",
"children":[
{
"name":"Level 1",
"children":[
{
"name":"Level 2",
"children":[
{
"name":"Level 3",
"children":[
{
"name":"Level 4",
"children":[
{
"name":"Speed",
"children":null,
"id":6
}
],
"id":5
}
],
"id":4
}
],
"id":3
}
],
"id":2
},
{
"name":"Level 1",
"children":[
{
"name":"Level 2",
"children":[
{
"name":"Level 3",
"children":[
{
"name":"Level 4",
"children":[
{
"name":"Cost",
"children":null,
"id":11
}
],
"id":10
}
],
"id":9
}
],
"id":8
}
],
"id":7
},
{
"name":"Level 1",
"children":[
{
"name":"Level 2",
"children":[
{
"name":"Level 3",
"children":[
{
"name":"Level 4",
"children":[
{
"name":"Manufacturability",
"children":null,
"id":16
}
],
"id":15
}
],
"id":14
}
],
"id":13
}
],
"id":12
}
],
"id":1
}
我试图了解如何搜索给定的id
值并更改其name
值。
在我的情况下,我知道我可以使用下面的代码使用d.id
和d.name
访问值(这是窗口小部件显示的一部分; name
值填充它)< / p>
var jstring = this.model.get('value') ? this.model.get('value') : "{}";
// where 'value' = demo.json
var root = JSON.parse(jstring)
var g = this.g = svg.selectAll("g")
.data(partition.nodes(root))
.enter().append("g");
var path = this.path = g.append("path")
.attr("d", arc)
.style("fill", function(d) {
d.active = d.active ? true : false
return d.active || d.center ? color[1] : color[0];
})
.on("dblclick",dblclick);
var text = this.text = g.append("text")
.attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; })
.attr("x", function(d) { return y(d.y); })
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.text(function(d) { return d.name; });
例如,如果我点击窗口小部件上的某个区域,我可以通过将其值设置为d.name
来填充输入框,它会为我提供正确的值。
function dblclick(d)
{
var input = document.getElementById("name");
input.value = d.name;
$( "#dialog" ).dialog(
{
buttons: {
Save: function() {
d.name = input.value;
var newString = JSON.stringify(root, function(key, val) {
if (Array.isArray(val)){
return val
}
if (val != null && typeof val == "object") {
val = _.pick(val, 'name', 'children', 'id');
if(d.id == val.id){
input.value = d.name;
console.log(d.name)
}
val.children = Array.isArray(val.children) ? val.children : [];
return val
}
return val
})
self.model.set('value', newString)
self.update()
console.log(newString)
我发现了一个类似的问题here,但我不明白如何应用修改我的JSON的答案。
这也是我尝试过的小提琴:http://jsfiddle.net/CVvW4/237/。我听了另一个问题的答案,但我的实施是错误的。
答案 0 :(得分:3)
以下是如何找到给定其id的节点:
f.tell()
现在,要更改名称,您只需执行以下操作:
var root = jsonStr
function findById(node, id) {
if (node.id == id) return node; // we found the node with the id given, return it
var result = null; // if the id wasn´t the one we were looking, we need to look if it is in its children
if (node.children) {
for (var i = 0; i < node.children.length && result == null; i++) {
result = findById(node.children[i], id)
}
}
return result; // return null if it wasn´t in its children, return the node if it was
}
console.log(findById(root, 16))
答案 1 :(得分:0)
我非常喜欢@juvian提供的接受答案,我已经投票了。
我提供这个,以显示如何命名子数组和我们希望为节点匹配的属性。我还按类型保护数组迭代。
我在这里提供了一些关于JSON,JavaScript对象以及何时解析的细节,何时不通过提供每个示例来解析。
请注意,我添加了一个小函数typeName
来帮助发现名称,因此我们不会尝试使用与我们属性相同的名称迭代非数组类型(null,string等)正在寻找。
注意:我没有防止属性与searchFor
值的类型匹配,但如果这很重要,则字符串"1"
与数字1
可以使用typeName
也是如此。
使用示例:https://jsfiddle.net/MarkSchultheiss/s4sxy4f6/
HERE是一个精简版本,我在尝试为其指定名称之前检查是否成功:https://jsfiddle.net/MarkSchultheiss/s4sxy4f6/1/
显示类型的代码和对象:
// this is just a string, but special as it is a JSON string and can be parsed
var myJSON = '{"children":[{"children":[{"children":[{"children":[{"children":[{"children":null,"id":6,"name":"Speed"}],"id":5,"name":"Level 4"}],"id":4,"name":"Level 3"}],"id":3,"name":"Level 2"}],"id":2,"name":"Level 1"},{"children":[{"children":[{"children":[{"children":[{"children":null,"id":11,"name":"Cost"}],"id":10,"name":"Level 4"}],"id":9,"name":"Level 3"}],"id":8,"name":"Level 2"}],"id":7,"name":"Level 1"},{"children":[{"children":[{"children":[{"children":[{"children":null,"id":16,"name":"Manufacturability"}],"id":15,"name":"Level 4"}],"id":14,"name":"Level 3"}],"id":13,"name":"Level 2"}],"id":12,"name":"Level 1"}],"_default":{},"id":1,"name":""}';
// This is a JavaScript Object
var myObject = {
"children": [{
"children": [{
"children": [{
"children": [{
"children": [{
"children": null,
"id": 6,
"name": "Speed"
}],
"id": 5,
"name": "Level 4"
}],
"id": 4,
"name": "Level 3"
}],
"id": 3,
"name": "Level 2"
}],
"id": 2,
"name": "Level 1"
}, {
"children": [{
"children": [{
"children": [{
"children": [{
"children": null,
"id": 11,
"name": "Cost"
}],
"id": 10,
"name": "Level 4"
}],
"id": 9,
"name": "Level 3"
}],
"id": 8,
"name": "Level 2"
}],
"id": 7,
"name": "Level 1"
}, {
"children": [{
"children": [{
"children": [{
"children": [{
"children": null,
"id": 16,
"name": "Manufacturability"
}],
"id": 15,
"name": "Level 4"
}],
"id": 14,
"name": "Level 3"
}],
"id": 13,
"name": "Level 2"
}],
"id": 12,
"name": "Level 1"
}],
"_default": {},
"id": 1,
"name": ""
};
// just to get the name of the objects type from the object prototype
function typeName(obj) {
// splits and returns second part of string such as "[object Array]" returns the "Array" removing the closing bracket
return Object.prototype.toString.call(obj).match(/.* (.*)\]/)[1];
}
// show some type names to assist with object "type" education
console.log("myJSON:" + typeName(myJSON)); // String
console.log("myObject:" + typeName(myObject)); // Object
console.log("Children of object:" + typeName(myObject.children)); // Array
console.log("Children Type:" + typeof myObject["children"] + " typeName:" + typeName(myObject.children));
console.log(Object.keys(myObject)); // thus we can get the string "children" from the object with Object.keys(myObject)[0]
var root = JSON.stringify(myObject); // create string of object
console.log("root:" + typeName(root)); // String
var newObject = JSON.parse(myJSON); // create new object of string
// create function with private name to call internally
// done this way to allow for external modification of the name without need to change the code inside it.
var findByProperty = function findNext(node, searchValue, propertyName, childName) {
if (node.hasOwnProperty(propertyName) && node[propertyName] == searchValue) return node; // node found return it
var result = null;
// has child array by the name and it is non-empty array
if (node.hasOwnProperty(childName) && typeName(node[childName]) === 'Array' && node[childName].length) {
for (var i = 0; i < node[childName].length && result == null; i++) {
result = findNext(node[childName][i], searchValue, propertyName, childName);
}
}
return result; // return null if not in children, return the node if it was
}
var searchFor = 16;
console.log('searchFor is a type of:'+typeName(searchFor));
var propertyName = "id";
var childrenArrayName = "children";
// show how we can return the found node then modify it
var found = findByProperty(myObject, searchFor, propertyName, childrenArrayName);
found.name = 'Freddy';
console.log(myObject);
console.log(myObject["children"][2]["children"][0]["children"][0]["children"][0]["children"][0].name); // logs "Freddy"
var secondfound = findByProperty(newObject, searchFor, propertyName, childrenArrayName);
secondfound.name = 'Walter';// modify the object via the node
console.log(newObject);
console.log(newObject["children"][2]["children"][0]["children"][0]["children"][0]["children"][0].name); // logs "Walter"
// just to show that the actual object is the one found
console.log(secondfound.name === newObject["children"][2]["children"][0]["children"][0]["children"][0]["children"][0].name); // logs true
以下是控制台日志的输出:
myJSON:String
VM78:125 myObject:Object
VM78:126 Children of object:Array
VM78:128 Children Type:object typeName:Array
VM78:129 ["children", "_default", "id", "name"]
VM78:132 root:String
VM205:148 searchFor is a type of:Number
VM281:153 Object {children: Array[3], _default: Object, id: 1, name: ""}
VM281:154 Freddy
VM337:158 Object {children: Array[3], _default: Object, id: 1, name: ""}
VM337:159 Walter
VM344:160 true