如何搜索JavaScript对象并更改值

时间:2016-05-13 16:39:04

标签: javascript

尝试理解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.idd.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/。我听了另一个问题的答案,但我的实施是错误的。

2 个答案:

答案 0 :(得分:3)

  • 您的jsonStr已经是一个json对象,无需进行字符串化和解析
  • 你有一个嵌套的结构,找到你需要递归函数的东西

以下是如何找到给定其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