How to traverse JSON object locating particular property and pushing its contents to array?

14,458

Solution 1

If the data was actually a JSON string, and not a JavaScript object, you could have something like:

// assuming `json` is the data string
var ids = [];
var data = JSON.parse(json, function(key, value) {
    if (key === "id") 
        ids.push(value);

    return value;
});

See reviver on JSON.parse method.

Solution 2

what you have is fine, but this is a little shorter and uses the .map function:

var jsonFile = require('./file_test.json'); // the above in my local directory
function traverse(obj) {
    var ids = [];
    for (var prop in obj) {
        if (typeof obj[prop] == "object" && obj[prop]) {
            if (prop == 'ids') {
                ids = obj[prop].map(function(elem){
                   return elem.id;
               })
            }
            ids =ids.concat(traverse(obj[prop]));
        }
    }
    return ids;
}

var ids =traverse(jsonFile);

console.log('ids', ids);
Share:
14,458
ahsteele
Author by

ahsteele

Professional success influenced by practical academics has shaped my outlook on software development. I have never stopped learning and am always interested in refining my development processes. For me it is not just the programming, all aspects of software development excite me.

Updated on June 07, 2022

Comments

  • ahsteele
    ahsteele almost 2 years

    I am working with a JSON object which can have a property ids at any leaf. I want to traverse the object and find all of the instances of the ids property and store each id in a collection.

    Mocked up JSON Object (the ids property could be at much deeper property locations).

    {
      "id": "b38a683d-3fb6-408f-9ef6-f4b853ed1193",
      "foo": {
        "ids": [
          {
            "id": "bd0bf3bd-d6b9-4706-bfcb-9c867e47b881"
          },
          {
            "id": "d1cc529d-d5d2-4460-b2bb-acf24a7c5999"
          },
          {
            "id": "b68d0c8c-548e-472f-9b01-f25d4b199a71"
          }
        ],
        "baz": "super"
      },
      "bar": {
        "ids": [
          {
            "id": "bd0bf3bd-d6b9-4706-bfcb-9c867e47b881"
          },
          {
            "id": "d1cc529d-d5d2-4460-b2bb-acf24a7c5999"
          },
          {
            "id": "b68d0c8c-548e-472f-9b01-f25d4b199a71"
          }
        ]
      }
    }
    

    I am using the following code to traverse the above JSON.

    var jsonFile = require('./file_test.json'); // the above in my local directory
    
    function traverse(obj, ids) {
      for (var prop in obj) {
        if (typeof obj[prop] == "object" && obj[prop]) {
          if (prop == 'ids') {
            for (var i = obj[prop].length - 1; i >= 0; i--) {
              ids.push(obj[prop][i]._id);
            };
          }
          traverse(obj[prop], ids);
        }
      }
    }
    
    var ids = new Array();
    traverse(jsonFile, ids);
    
    console.log('ids', ids);
    

    The above nets the following:

    ids
    [
      'b68d0c8c-548e-472f-9b01-f25d4b199a71',
      'd1cc529d-d5d2-4460-b2bb-acf24a7c5999',
      'bd0bf3bd-d6b9-4706-bfcb-9c867e47b881',
      'b68d0c8c-548e-472f-9b01-f25d4b199a71',
      'd1cc529d-d5d2-4460-b2bb-acf24a7c5999',
      'bd0bf3bd-d6b9-4706-bfcb-9c867e47b881'
    ]
    

    While my code works I am not convinced that I am doing this the most efficient or best way. Is there a better way to find all instances of the ids property? Perhaps without passing in an array but returning one? Or setting up for a callback with an ids array?