JavaScript中查找和替换JSON对象数组中的嵌套数组

7

我有一个这样的JSON对象:

var myObject = [    
{
    "Name" : "app1",
    "id" : "1",
    "groups" : [
        { "id" : "test1", 
          "name" : "test group 1", 
          "desc" : "this is a test group"
         },
        { "id" : "test2",
          "name" : "test group 2",
          "desc" : "this is another test group"
         }
    ]
},
{
    "Name" : "app2",
    "id" : "2",
    "groups" : [
        { "id" : "test3", 
          "name" : "test group 4", 
          "desc" : "this is a test group"
         },
        { "id" : "test4",
          "name" : "test group 4",
          "desc" : "this is another test group"
         }
    ]
},
 {
    "Name" : "app3",
    "id" : "3",
    "groups" : [
        { "id" : "test5", 
          "name" : "test group 5", 
          "desc" : "this is a test group"
         },
        { "id" : "test6",
          "name" : "test group 6",
          "desc" : "this is another test group"
         }
    ]
}

];

我有一个特定“id”的“name”新值可用。

如何替换任何对象中特定“id”的“name”?

还有,如何计算所有对象中组的总数?

例如:将名称替换为“test grp45”,以便id =“test1”

这里是fiddle http://jsfiddle.net/qLTB7/21/


可能是访问/处理嵌套对象、数组或JSON的重复问题。 - Qantas 94 Heavy
3
这不是一个 JSON 对象,它只是一个 JavaScript 对象。 - zerkms
是的,我的错误!它是JS对象。无论如何还是谢谢。 - surfnerd
@zerkms - myObject 是一个数组(虽然它是一种特殊类型的对象)。;-) - RobG
在外部对象中,您有“Name”,在内部对象中,您有“name”,这样是否正确? - RobG
6个回答

17
以下函数将搜索一个对象及其所有子对象/数组,并用新值替换键。它将全局应用,因此它不会在第一次替换后停止。取消注释已注释的行以使其成为这种方式。

以下函数将搜索一个对象及其所有子对象/数组,并用新值替换键。它将全局应用,因此它不会在第一次替换后停止。取消注释已注释的行以使其成为这种方式。

function findAndReplace(object, value, replacevalue) {
  for (var x in object) {
    if (object.hasOwnProperty(x)) {
      if (typeof object[x] == 'object') {
        findAndReplace(object[x], value, replacevalue);
      }
      if (object[x] == value) { 
        object["name"] = replacevalue;
        // break; // uncomment to stop after first replacement
      }
    }
  }
}

可工作的jsfiddle示例:http://jsfiddle.net/qLTB7/28/


你可以使用 return 来代替 break,以使停止更加明显。此外,typeof object[x] == typeof {} 非常低效(它会每次创建一个新对象),应该使用 typeof object[x] == 'object'。同时,还应该包括一个 hasOwnProperty 测试,以避免检查继承的可枚举属性。 - RobG
@RobG - 我很快地写了这个。我会添加那些更改。 - PitaJ

1

试试这个

function findAndReplace(object,keyvalue, name) {
    object.map(function (a) {
        if (a.groups[0].id == keyvalue) {
            a.groups[0].name = name
        }
    })
}

findAndReplace(myObject,"test1" ,"test grp45");

谢谢Manjesh。PitaJ建议了完全相同的方法。成功了! - surfnerd

1

也许有更简洁的解决方案

function changeName(objArray, objId, newName) {
    objArray.forEach(function(obj) {
        if (obj.id === objId) obj.Name = newName;
    });
}

个人而言:如果是我,创建这些对象时,我会创建一个新的obj并以其id作为key。

 var myApps = {};
 myObject.forEach(function(o) {
     myApps[o.id] = o;
 });

=>
{
    "1": {
        "Name": "app1",
        "id": "1",
        "groups": [
            {
                "id": "test1",
                "name": "test group 1",
                "desc": "this is a test group"
            },
            {
                "id": "test2",
                "name": "test group 2",
                "desc": "this is another test group"
            }
        ]
    }
}

然后你可以这样做:

myApps['someId'].name = 'This is my new Name'

在这里查看: http://jsfiddle.net/qLTB7/40/


嗨,托德。谢谢你的反馈。我们可以直接使用Object[0],Object[1]来完成相同的操作,对吧? - surfnerd
这仅适用于第一个数组中的对象,它不会递归到“groups”数组中的对象。即使找到匹配项,它也会继续循环。 - RobG
@vkaiz 是的,我们可以按照您所描述的迭代方式来实现。我原以为您只是在寻找一种通过ID选择对象并更改名称属性的方法。 - Todd
@RobG,感谢你指出循环在检查完所有对象之前都不会中断。另外,我没有理解到需要进行“深度”名称更改。 - Todd
1
@Todd - OP说:“我如何替换任何对象中特定“id”的“name””,因此我假设它可以在任何级别上。我可能是错的,只有OP知道。 :-) - RobG
@RobG,感谢您对细节的关注。继续让SO变得更好! - Todd

1
这里有一个不同的方法,使用Array.prototype.some。它假设外部对象中的Name属性实际上应该是name(注意大小写)。
function updateNameById(obj, id, value) {
  Object.keys(obj).some(function(key) {
    if (obj[key].id == id) {
      obj[key].name = value;
      return true;  // Stops looping
    }
      // Recurse over lower objects
      else if (obj[key].groups) {
      return updateNameById(obj[key].groups, id, value);
    }
  })
}

一些函数的优点在于它会在回调函数返回 true 时立即停止。

0

我认为这对你应该有效:

var id = 'test1';
var newname = 'test grp45';
var numberOfGruops = 0;
myObject.forEach(function(app){
numberOfGruops += app.groups.length;    //Count all groups in this app
app.groups.forEach(function(group){
    if(group.id===id)
        group.name = newname;   // replace the name
});
});

0

在 PitaJ 的回答的第 7 行中,应该是 if (object["id"] == value) 而不是 if (object[x] == value),因此整个函数应该如下所示:

function findAndReplace(object, value, replacevalue) {
  for (var x in object) {
    if (object.hasOwnProperty(x)) {
      if (typeof object[x] == 'object') {
        findAndReplace(object[x], value, replacevalue);
      }
      if (object["id"] == value) { 
        object["name"] = replacevalue;
        // break; // uncomment to stop after first replacement
      }
    }
  }
}

如果您离开 object[x],函数将替换名称,同时也会替换其他键值设置为 "test1" 的对象的名称,例如{"id": "xxx", "name": "test group 1", "desc": "test1"}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接