Join the Stack Overflow Community
Stack Overflow is a community of 6.6 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I have one JSON Object like this :

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"
         }
    ]
}

];

I have new value available of "name" for specific "id". How can I replace "name" of specific "id" inside any object ?

And how to count total number of groups among all objects ?

for example : replace name to "test grp45" for id = "test1"

Here is fiddle http://jsfiddle.net/qLTB7/21/

share|improve this question
    
possible duplicate of Access / process (nested) objects, arrays or JSON – Qantas 94 Heavy Jun 30 '14 at 4:21
3  
It's not a JSON object, it is just a javacsript object. – zerkms Jun 30 '14 at 4:23
    
Yes. My mistake !. It's JS object. Thanks anyways. – vkaiz Jun 30 '14 at 4:37
    
@zerkms— *myObject * is an Array (which, granted, is a particular kind of Object). ;-) – RobG Jun 30 '14 at 4:50
    
In the outer object you have "Name", the inner objects you have "name", is that how it should be? – RobG Jun 30 '14 at 6:30
up vote 6 down vote accepted

The following function will search through an object and all of its child objects/arrays, and replace the key with the new value. It will apply globally, so it won't stop after the first replacement. Uncomment the commented line to make it that way.

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

Working jsfiddle: http://jsfiddle.net/qLTB7/28/

share|improve this answer
    
Thanks a lot. This worked perfectly fine. – vkaiz Jun 30 '14 at 4:37
    
Instead of break you could use return to make it more obvious that it stops there. Also, typeof object[x] == typeof {} is very inefficient (it creates a new object every time), use typeof object[x] == 'object'. Also should include a hasOwnProperty test, you don't want to check inherited enumerable properties. – RobG Jun 30 '14 at 4:45
    
@RobG - I wrote this up real quickly. I will add those changes. – PitaJ Jun 30 '14 at 4:51
    
Will this work for object replacements? – forgottofly Mar 16 '16 at 4:42

Try this

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");
share|improve this answer
    
I got it. I didnt see your updated output. – vkaiz Jun 30 '14 at 4:30
    
Thanks Manjesh. PitaJ suggested exactly same. Worked ! – vkaiz Jun 30 '14 at 4:38

I think this should work for you:-

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
});
});
share|improve this answer

Maybe a more succinct sol'n

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

Personally: if this were me, when creating these objects, I would create a new obj and key them by id.

 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"
            }
        ]
    }
}

And then you could just do:

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

Check it out here: http://jsfiddle.net/qLTB7/40/

share|improve this answer
    
Hi Todd..Thank you for feedback..we can directly do the same with Object[0] , Object[1] right ? – vkaiz Jun 30 '14 at 5:09
    
That only works for objects in the first array, it doesn't recurse into the objects in the groups array. It also continues looping, even after a match has been found. – RobG Jun 30 '14 at 6:40
    
@vkaiz yes, we could do that in an iterative way, as you're describing. I thought you were just looking for a way to select an object by its ID, then change the name property. – Todd Jun 30 '14 at 14:17
    
@RobG, thanks for pointing out that the loop isn't broken until ALL objs are checked. On a different note, I didn't understand that "deep" name changing was needed. – Todd Jun 30 '14 at 14:20
1  
@Todd—the OP says "How can I replace "name" of specific "id" inside any object", so I assumed it could be at any level. I might be wrong, only the OP knows. :-) – RobG Jun 30 '14 at 23:15

Here's a different approach using Array.prototype.some. It assumes that the Name property in the outer objects should be actually be name (note capitalisation).

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

The advantage of some is that it stops as soon as the callback returns true.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.