Get all keys of a deep object in Javascript
is that possible using nodejs maybe with the help of plugins?
7 Answers 7
You can do this by recursively traversing the object:
function getDeepKeys(obj) < var keys = []; for(var key in obj) < keys.push(key); if(typeof objJavascript get all keys in array === "object") < var subkeys = getDeepKeys(objJavascript get all keys in array); keys = keys.concat(subkeys.map(function(subkey) < return key + "." + subkey; >)); > > return keys; >
Running getDeepKeys(abc) on the object in your question will return the following array:
["1", "2", "3", "4", "5", "5.test", "5.tester", "5.tester.name", "count", "counter", "counter.count"]
Just found an issue in your example. What happens if they key is a number? example: abc.test[0] — Your example will output abc.test.0 which is wrong.
@GeorgiK. JavaScript doesn’t distinguish between string keys and numeric keys. test[0] and test[«0»] are the same thing. I’m not sure what purpose you’re using this code for, why do you need to make this distinction?
Found this answer through google and adjusted it slightly for my personal need with an added if/else and TypeScript types. Sharing it forward for other googlers like myself: paste.ee/p/US30f (paste seeing as code in a comment lacks formatting)
Smaller version, no side effect, just 1 line in function body:
function objectDeepKeys(obj) < return Object.keys(obj).filter(key =>objJavascript get all keys in array instanceof Object).map(key => objectDeepKeys(objJavascript get all keys in array).map(k => `$.$`)).reduce((x, y) => x.concat(y), Object.keys(obj)) >
var abc = < 1: "Raggruppamento a 1", 2: "Raggruppamento a 2", 3: "Raggruppamento a 3", 4: "Raggruppamento a 4", count: '3', counter: < count: '3', >, 5: < test: "Raggruppamento a 1", tester: < name: "Ross" >> >; function objectDeepKeys(obj) < return Object.keys(obj) .filter(key =>objJavascript get all keys in array instanceof Object) .map(key => objectDeepKeys(objJavascript get all keys in array).map(k => `$.$`)) .reduce((x, y) => x.concat(y), Object.keys(obj)) > console.log(objectDeepKeys(abc))
I know this is bit old post.
This code covers all criteria in JSON object format like just object,object array, nested array object,nested object with array object etc.
getDeepKeys = function (obj) < var keys = []; for(var key in obj) < if(typeof objJavascript get all keys in array === "object" && !Array.isArray(objJavascript get all keys in array)) < var subkeys = getDeepKeys(objJavascript get all keys in array); keys = keys.concat(subkeys.map(function(subkey) < return key + "." + subkey; >)); > else if(Array.isArray(objJavascript get all keys in array)) < for(var i=0;i)); > > else < keys.push(key); >> return keys; >
Thanks! This is exactly what I was looking for. I like this because, unlike the accepted answer, it returns the deepest keys instead of all keys: [ ‘1’, ‘2’, ‘3’, ‘4’, ‘5.test’, ‘5.tester.name’, ‘count’, ‘counter.count’, ]
Consider an implementation of deepKeys using functional style. We can avoid headaches of mutation, variable reassignment, intermediate assignments, and other side effects —
- If the input t is an object, for each (k,v) pair in the object, append k to the path and recur on the sub-problem, v
- (induction) the input is not an object. return the formatted path
We can encode this as follows —
const deepKeys = (t, path = []) => Object(t) === t ? Object // 1 .entries(t) .flatMap(([k,v]) => deepKeys(v, [. path, k])) : [ path.join(".") ] // 2 const input = ,5:>> for (const path of deepKeys(input)) console.log(path)
Another great choice to implement this program is JavaScript’s generators. Notice the similarity between this deepKeys and the implementation above. They both effectively do the same thing —
function* deepKeys (t, path = []) < switch(t?.constructor) < case Object: for (const [k,v] of Object.entries(t)) // 1 yield* deepKeys(v, [. path, k]) break default: yield path.join(".") // 2 >> const input = ,5:>> for (const path of deepKeys(input)) console.log(path)
Output is the same for each variant of deepKeys —
1 2 3 4 5.test 5.tester.name count counter.count
Get array of object’s keys
I would like to get the keys of a JavaScript object as an array, either in jQuery or pure JavaScript. Is there a less verbose way than this?
var foo = < 'alpha' : 'puffin', 'beta' : 'beagle' >; var keys = []; for (var key in foo)
@unsynchronized Please never post solutions as comments. Your comment intentionally breaches the clear and intentional page structure design.
8 Answers 8
var foo = < 'alpha': 'puffin', 'beta': 'beagle' >; var keys = Object.keys(foo); console.log(keys) // ['alpha', 'beta'] // (or maybe some other order, keys are unordered).
This is an ES5 feature. This means it works in all modern browsers but will not work in legacy browsers.
MDN also has the above referred Polyfill, but notes bugs in IE7 and maybe 8, then refers off to a much shorter Polyfill here: tokenposts.blogspot.com.au/2012/04/…
the amount of times I tried to call keys as a property of an instance before it dawned on me it’s a static class method. comprehension of api—
var foo = < 'alpha' : 'puffin', 'beta' : 'beagle' >, keys = $.map(foo, function(v, i)< return i; >);
Of course, Object.keys() is the best way to get an Object’s keys. If it’s not available in your environment, it can be trivially shimmed using code such as in your example (except you’d need to take into account your loop will iterate over all properties up the prototype chain, unlike Object.keys() ‘s behaviour).
However, your example code.
var foo = < 'alpha' : 'puffin', 'beta' : 'beagle' >; var keys = []; for (var key in foo)
. could be modified. You can do the assignment right in the variable part.
var foo = < 'alpha' : 'puffin', 'beta' : 'beagle' >; var keys = [], i = 0; for (keys[i++] in foo) <>
Of course, this behaviour is different to what Object.keys() actually does (jsFiddle). You could simply use the shim on the MDN documentation.
Getting JavaScript object key list
The fact that it works in Chrome also means it works in Node.js as both are built on the V8 javascript engine.
Note that this is different from for(key in ob) ! Object.keys wont list the keys from prototypes, but .. in obj does.
@fet windows7 came with IE8. As great as it would be, there’s no way this can be the accepted answer until people stop using IE8.
Here developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… you find a JavaScript method that works correctly in old browsers and doesn’t overwrite the functionality in newer browsers. Also see my answer below.
var obj = < key1: 'value1', key2: 'value2', key3: 'value3', key4: 'value4' >; var keys = []; for (var k in obj) keys.push(k); console.log("total " + keys.length + " keys: " + keys);
I don’t suppose Javascript is like PHP, where you can skip the first line altogether? Not that something like that is advisable to do anyway.
You should take a look at David Morrissey’s comment below for an edge case here. Sometimes taking this approach will result in unwanted members of the prototype showing up in keys .
@pat: If you’re using object literals, that’ll only happen if you extend Object.prototype , which you should not be doing anyway. For custom constructors, though, you are right.
@BartvanHeukelom even back in june 2010 that caused a notice, as it means you’re implicitly typing the object. Assigning [] to it (or array() back then) makes it an array, which you can then use as an array safely.
Underscore.js makes the transformation pretty clean:
var keys = _.map(x, function(v, k) < return k; >);
Edit: I missed that you can do this too:
If you only want the keys which are specific to that particular object and not any derived prototype properties:
function getKeys(obj) < var r = [] for (var k in obj) < if (!obj.hasOwnProperty(k)) continue r.push(k) >return r >
var keys = getKeys() var length = keys.length // access the `length` property as usual for arrays
var keys = new Array(); for(var key in obj) < keysJavascript get all keys in array = key; >var keyLength = keys.length;
to access any value from the object, you can use objJavascript get all keys in array;
array index is incremented automatically by keys.length , which is different for each iteration as each iteration inserts a value.
to get the list of keys or
[obj[index] for (index in obj)]
Anurags answer is basically correct. But to support Object.keys(obj) in older browsers as well you can use the code below that is copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys . It adds the Object.keys(obj) method if it’s not available from the browser.
if (!Object.keys) < Object.keys = (function() < 'use strict'; var hasOwnProperty = Object.prototype.hasOwnProperty, hasDontEnumBug = !(< toString: null >).propertyIsEnumerable('toString'), dontEnums = [ 'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor' ], dontEnumsLength = dontEnums.length; return function(obj) < if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) < throw new TypeError('Object.keys called on non-object'); >var result = [], prop, i; for (prop in obj) < if (hasOwnProperty.call(obj, prop)) < result.push(prop); >> if (hasDontEnumBug) < for (i = 0; i < dontEnumsLength; i++) < if (hasOwnProperty.call(obj, dontEnums[i])) < result.push(dontEnums[i]); >> > return result; >; >()); >
Use Object.keys() . it’s the way to go.
Full documentation is available on the MDN site linked below:
Note that in coffeescript this can be accomplished in all browsers and node as
Recursive solution for browsers that support ECMAScript 5:
var getObjectKeys = function(obj) < var keys = Object.keys(obj); var length = keys.length; if (length !== 0) < for (var i = 0; i < length; i++) < if (typeof objJavascript get all keys in array] === 'object') < keysJavascript get all keys in array] = getObjectKeys(objJavascript get all keys in array]); >> > return keys; >;
var obj = < key1: 'value1', key2: 'value2', key3: 'value3', key4: 'value4' >console.log(Object.keys(obj)); console.log(Object.keys(obj).length)
If you decide to use Underscore.js you better do
var obj = < key1: 'value1', key2: 'value2', key3: 'value3', key4: 'value4' >var keys = []; _.each( obj, function( val, key ) < keys.push(key); >); console.log(keys.lenth, keys);
In JavaScript, an object is a standalone entity, with properties and type.
For fetching values from Object in form of array: Object.values(obj) // obj is object name that you used Result -> [«value1», «value2», «value3», «value4»]
For fetching keys from Object in form of array: Object.keys(obj) // obj is object name that you used Result -> [«key1», «key2», «key3», «key4»]
As both functions are returning array you can get the length of keys or value by using length property. For instance — Object.values(obj).length or Object.keys(obj).length
Getting a list of associative array keys
Just to get the terminology correct — there is no such thing as an ‘associative array’ in JavaScript — this is technically just an object and it is the object keys we want.
Thanks for clarifying the terminology! Can you maybe make that a bit bigger in bright red blinking lights?
6 Answers 6
var keys = []; for (var key in dictionary) < if (dictionary.hasOwnProperty(key)) < keys.push(key); >>
hasOwnProperty is needed because it’s possible to insert keys into the prototype object of dictionary . But you typically don’t want those keys included in your list.
For example, if you do this:
Object.prototype.c = 3; var dictionary = ;
and then do a for. in loop over dictionary , you’ll get a and b , but you’ll also get c .
@b00t i though that by declaring a variable inside a for loop. it wouln’t be set in global space. now you made me doubt hehe 🙂
@mzalazar, but you’re not declaring it (keys) at any point if you’re just using keys.push(key); . You’re just pulling (and thus declaring it) from the global namespace. 🙂
for (var key in dictionary) < // Do something with key >
Just noticed that there should be a colon instead of a comma between «dogs» and the array above. Assume it’s due to transcription.
Very important to check for dictionary.hasOwnProperty(key) otherwise you may end up with methods from the prototype chain..
From the same article: Iterates over the enumerable properties of an object, in arbitrary order. If key order is important, you need to do something like pushing them in an array, sorting it, and then using a for() loop to get keys from the sorted array with which to index the original object.
It is, of course, fair to optimize by omitting the dictionary.hasOwnProperty check if you can be confident that the object lacks a prototype. But it’s important to be aware of the possibility of prototype inheritance in this context, since JavaScript dictionaries are really objects.
You can use: Object.keys(obj)
var dictionary = < "cats": [1, 2, 37, 38, 40, 32, 33, 35, 39, 36], "dogs": [4, 5, 6, 3, 2] >; // Get the keys var keys = Object.keys(dictionary); console.log(keys);
See reference below for browser support. It is supported in Firefox 4.20, Chrome 5, and Internet Explorer 9. Object.keys() contains a code snippet that you can add if Object.keys() is not supported in your browser.
I’m switching this to the accepted answer now. Only IE8 doesn’t support it anymore (for which a polyfill is available developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…)
Just a quick note. Be wary of using for..in if you use a library (jQuery, Prototype, etc.), as most of them add methods to created Objects (including dictionaries).
This will mean that when you loop over them, method names will appear as keys. If you are using a library, look at the documentation and look for an enumerable section, where you will find the right methods for iteration of your objects.
DictionaryObj being the JavaScript dictionary object you want to go through. And value, key of course being the names of them in the dictionary.
$.each(DictionaryObj, function (key, value) ") .attr("value", key) .text(value)); >);
@Exzile The argument names in your function definition are very confusing. It says at api.jquery.com/jquery.each that the callback is Function( String propertyName, Object valueOfProperty ). Your names imply the reverse.
And in a file loaded early on I have some lines of code borrowed from elsewhere on the Internet which cover the case of old versions of script interpreters that do not have Object.keys built in.
if (!Object.keys) < Object.keys = function(object) < var keys = []; for (var o in object) < if (object.hasOwnProperty(o)) < keys.push(o); >> return keys; >; >
I think this is the best of both worlds for large projects: simple modern code and backwards compatible support for old versions of browsers, etc.
Effectively it puts JW’s solution into the function when Rob de la Cruz’s Object.keys(obj) is not natively available.