2

I have the following json object in node.js.

x={
    '40': {
        length: '2',
        data: ['11', '22']
    },
    '41': {
        length: '1',
        data: ['fe']
    },
    '42': {
        length: '2',
        data: ['ef', 'ab']
    },  
}

Suppose I do not know in advance what will be the property name inside x. However, I would like to retrieve every property and its associated value. How can this be done?

I am using node.js

4 Answers4

4

First, that's not JSON. That's a JavaScript object initializer. JSON is a textual notation. If you're dealing with JavaScript source code, and not dealing with a string, you're not dealing with JSON. (If that were a string, it would be invalid JSON; JSON requires that keys and strings be in double quotes, not single quotes.)

You can find out what the keys in the x object are using for-in or Object.keys:

for-in:

var key;
for (key in x) {
    // key is the key
    // x[key] is the value
}

With the latest NodeJS, you can use JavaScript's new let to keep key scoped just to the loop:

for (let key in x) {
    // key is the key
    // x[key] is the value
}

Object.keys:

Object.keys(x).forEach(function(key) {
    // key is the key
    // x[key] is the value
});

In recent versions of NodeJS you can use JavaScript's new arrow function as the callbck to make things more concise:

Object.keys(x).forEach(key => {
    // key is the key
    // x[key] is the value
});

If you need to descend into the objects contained with x, you simply recurse.

Note that for-in will visit the object's enumerable properties, including any enumerable properties on its prototype(s). Object.keys will give you an array of the object's own enumerable properties (only).

Example of forEach:

var x = {
    '40': {
        length: '2',
        data: ['11', '22']
    },
    '41': {
        length: '1',
        data: ['fe']
    },
    '42': {
        length: '2',
        data: ['ef', 'ab']
    },  
};
Object.keys(x).forEach(function(key) {
    console.log(key + ": length = " + x[key].length);
});
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks. I prefer the `for-in` method. Looks more readable. But is Object.keys more powerful? It looks like it can do more. –  Mar 16 '16 at 09:25
  • 1
    @LitAiy: One of the nice things about using `Object.keys` is that you get a nice contained scope for your `key` and perhaps `value` variable (the scope of the callback). But you can use JavaScript's new `let` to do that with `for-in`, too. – T.J. Crowder Mar 16 '16 at 09:27
  • thanks for the answer and explanation. Apologies for switching answer to Andy but his answer was more complete for my question. –  Mar 16 '16 at 09:33
1

Use recursion to find the key/values of all objects nested or otherwise:

function finder(obj) {

  // for each property in the object passed into
  // the function...
  for (var p in obj) {

    // if its value is another object (see appended note)...
    if (Object.prototype.toString.call(obj[p]).slice(8, -1) === 'Object') {

      // ...log the key to the console and then call finder()
      // again with this current object (this is the recursive part)
      console.log('key: ' + p + ', value: Object');
      finder(obj[p]);

    // otherwise log the key/value
    } else {
      console.log('key: ' + p + ', value: ', obj[p]);
    }
  }
}

finder(x);

OUTPUT

key: 40, value: Object
key: length, value:  2
key: data, value:  Array [ "11", "22" ]
key: 41, value: Object
key: length, value:  1
key: data, value:  Array [ "fe" ]
key: 42, value: Object
key: length, value:  2
key: data, value:  Array [ "ef", "ab" ]

NOTE

This rather long-winded line of code to check if a value is an object

Object.prototype.toString.call(obj[p]).slice(8, -1) === 'Object'

is necessary because typeof obj[p] === 'object' will return true for arrays and null too. It's a bit of a gotcha.

Object.prototype.toString.call({})

returns a string like "[object Object]", and the slice grabs the relevant section of the string.

Andy
  • 61,948
  • 13
  • 68
  • 95
0

You can use Object.keys():

Object.keys(x).forEach(v => {
    console.log(v);  // logs the key
    console.log(x[v])  // logs the key's value
})
baao
  • 71,625
  • 17
  • 143
  • 203
-1

Optimizing the Andy's code

var x = {
        '40': {
            length: '2',
            data: ['11', '22']
        },
        '41': {
            length: '1',
            data: ['fe']
        },
        '42': {
            length: '2',
            data: ['ef', 'ab']
        },  
    };



function finder(obj) {
   
  if (Object.prototype.toString.call(obj).slice(8, -1) === 'Object') {

    for (var p in obj) {
        console.log('key: ' + p + ', type: object');
        finder(obj[p]);
     } 
  } else {
      console.log('key: ' + obj + ', value: ', obj);
  }
  
}

finder(x);
Manoj H L
  • 843
  • 9
  • 22
  • The property names `length` and `data` are not known. – Andy Mar 16 '16 at 09:12
  • While this code snippet may solve the question, [including an explanation](http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations! – Tobi Nary Mar 16 '16 at 09:39
  • Thanks I'll add some – Manoj H L Mar 16 '16 at 09:45