2016-05-13 8 views
4

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値がそれを移入)

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; }); 

例えば、Iウィジェット上の特定の領域をクリックすると、その値を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

正確に達成しようとしているのは何ですか?クリックイベントハンドラコードはどこですか?あなたはもっと具体的になりますか? – iulian

+0

データツリーの特定の 'id'値を検索していますか?その場合は、検索関数を再帰的に呼び出す必要があります。 – C14L

+0

@iulianそれはあまりにも多くのコードだと思ったので私はそれを残しましたが、私はそれを追加する編集します – c2bh2016

答えて

3
  • あなたjsonStrがすでにJSONオブジェクトで、それを文字列化して解析する必要
  • あなたはここで

再帰関数が必要になります何かを見つけるために、ネストされた構造を有しているが見つける方法はありません今

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)) 

、その名前を変更するには、単に行うことができます:ノードは、そのIDを与え

findById(root, 16).name = 'asd'; 
+0

詳細な説明をいただきありがとうございます。あなたの関数を私のクリックイベントに加え、コンソールでnewStringとrootの正しい値の変更を見ることができますが、jstring変数は変更されません。あなたは見てみることができますか? https://jsfiddle.net/baqxh3sf/ – c2bh2016

+0

@ c2bh2016 console.log(jstring)の代わりにself.model.get( 'value')を試してみてください – juvian

+0

私は試しましたが、ウィジェットに変更はありませんでした。他の提案? – c2bh2016

0

私は、私がup-votedした@juvianによって提供された受け入れられた回答が本当に好きです。

これは、ノードに対して照合する子配列とプロパティの名前付け方法を示すために提供します。私はまた型によって配列の反復を保護します。

ここでは、JSON、JavaScriptオブジェクト、および解析するタイミングについて、それぞれの例を示して解析しない場合の詳細を示します。

名前の検出を支援するために小さな関数typeNameを追加したので、検索対象のプロパティと同じ名前で非配列型(nullの文字列など)を反復しようとしません。

注:私はsearchFor値に対するプロパティの型マッチングを防ぐことはできませんでしたが、それが重要だった場合、文字列"1"は数1対あなたにもtypeNameを使用して強化して置くことができます。

:タイプを表示する https://jsfiddle.net/MarkSchultheiss/s4sxy4f6/1/

コードとオブジェクト:

と遊ぶの例:HERE https://jsfiddle.net/MarkSchultheiss/s4sxy4f6/

は、私が前にそれに名前を代入しようとし、成功のためのチェックストリップダウンバージョンです。ここで

// 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 
関連する問題