Javascript - removing undefined fields from an object
Solution 1
A one-liner using ES6 arrow function and ternary operator:
Object.keys(obj).forEach(key => obj[key] === undefined ? delete obj[key] : {});
Or use short-circuit evaluation instead of ternary: (@Matt Langlois, thanks for the info!)
Object.keys(obj).forEach(key => obj[key] === undefined && delete obj[key])
Same example using if statement:
Object.keys(obj).forEach(key => {
if (obj[key] === undefined) {
delete obj[key];
}
});
If you want to remove the items from nested objects as well, you can use a recursive function:
const removeEmpty = (obj) => {
let newObj = {};
Object.keys(obj).forEach((key) => {
if (obj[key] === Object(obj[key])) newObj[key] = removeEmpty(obj[key]);
else if (obj[key] !== undefined) newObj[key] = obj[key];
});
return newObj;
};
Solution 2
I prefer to use something like Lodash:
import { pickBy, identity } from 'lodash'
const cleanedObject = pickBy(originalObject, identity)
Note that the identity function is just x => x
and its result will be false for all falsy values. So this removes undefined, "", 0, null, ...
If you only want the undefined
values removed you can do this:
const cleanedObject = pickBy(originalObject, v => v !== undefined)
It gives you a new object, which is usually preferable over mutating the original object like some of the other answers suggest.
Solution 3
Use JSON Utilities
Overview
Given an object like:
var obj = { a: 1, b: undefined, c: 3 }
To remove undefined
props in an object we can use nested JSON methods stringify and parse like so:
JSON.parse(JSON.stringify(obj))
Live Example
var obj = { a: 1, b: undefined, c: 3 }
var output = JSON.parse(JSON.stringify(obj));
console.log(output)
Limitations and warnings
Depending on how Javascript is implemented.
- It is possible that
undefined
will be converted tonull
instead of just being removed. - Nested
Object
,Array
will be converted to strings Date
,time
values also converted to strings
Tested
The above code was tested in Firefox, Chrome, and Node 14.18.1 and removed "b" from all obj arrays. Still I recommend exercising caution using this method unless you are in a stable environment (such as cloud functions or docker) I would not rely on this method client side.
Solution 4
Because it doesn't seem to have been mentioned, here's my preferred method, sans side effects or external dependencies:
const obj = {
a: 1,
b: undefined
}
const newObject = Object.keys(obj).reduce((acc, key) => {
const _acc = acc;
if (obj[key] !== undefined) _acc[key] = obj[key];
return _acc;
}, {})
console.log(newObject)
// Object {a: 1}
Solution 5
This solution also avoids hasOwnProperty()
as Object.keys returns an array of a given object's own enumerable properties.
Object.keys(obj).forEach(function (key) {
if(typeof obj[key] === 'undefined'){
delete obj[key];
}
});
and you can add this as null
or ''
for stricter cleaning.
Related videos on Youtube
Damian
Updated on December 19, 2021Comments
-
Damian over 2 years
Is there a clean way to remove undefined fields from an object?
i.e.
> var obj = { a: 1, b: undefined, c: 3 } > removeUndefined(obj) { a: 1, c: 3 }
I came across two solutions:
_.each(query, function removeUndefined(value, key) { if (_.isUndefined(value)) { delete query[key]; } });
or:
_.omit(obj, _.filter(_.keys(obj), function(key) { return _.isUndefined(obj[key]) }))
-
Amadan over 9 yearsWhat is your question? Your solutions already do what you want (destructively and nondestructively, respectively).
-
Abdul Jabbar over 9 yearsHow much more cleaner do you want it to be, it is already clean!
-
sean about 8 yearsI would use just
_.filter(obj, function(v) { return _.isUndefined(v)})
-
Noel Llevares about 7 yearsI wonder which of these answers is the fastest?
-
Andreas Warberg almost 6 yearsYour
omit
example simplifies to_.omit(obj, _.isUndefined)
(Underscore only) -
Ryan Allen about 2 yearsWith lodash:
_.omitBy(obj, _.isUndefined)
-
-
jfriend00 over 9 yearsExcept
Object.keys()
has it's own overhead in creating an entire array of the keys and it requires at least IE 9. -
Matt Langlois almost 8 yearsYou actually don't even need the ternary operator. Instead you can do
(obj[key]===undefined&& delete obj[key])
The reason this works is because and uses short-circuit evaluation, so once the first check fails the second isn't even evaluated. -
Rotareti almost 8 yearsEven better! I updated the answer. Thanks for mentioning it :)
-
ptim over 7 yearsbtw, I'm aliasing
_acc
to avoid the eslint error no-param-reassign -
Glenn Plas almost 7 yearsthis will replace the
undefined
withnull
and the entries are still there. -
nmanikiran almost 7 years@GlennPlas add a plnkr plnkr.co/edit/wP37G6BA5uJPSFz6xLTq?p=preview check browser console for output
-
Glenn Plas almost 7 yearsIndeed, strange I tested this in a project and it didn't work (I was using geojson objects and tried to clean out undefined features ), but this example indeed does what it says.
-
Glenn Plas almost 7 yearsActually, I recall the issue now, I had undefined keys, not values of valid keys. probably was a bit too quick to comment here. Tx.
-
pandark about 6 years
!obj[key]
will not only removenull
,''
andundefined
, but also remove0
andNaN
. -
David almost 6 yearsI started using the
filter
+forEach
and ended up transforming it to areduce
like this. +1 -
sowdri almost 6 yearsGuys, this might look simple, but date objects will be converted to string. Beware
-
CertainPerformance almost 6 yearsSO isn't a code-golfing site - clean, readable code is much more important than as short as possible code. The conditional operator is appropriate when you need to do something with the result of the expression, which is not the case here. If you just need to imitate
if/else
, I think it would be best to just useif/else
. -
Rotareti almost 6 years@CertainPerformance Fair point. I added an example using an
if
expression. -
Kmaid almost 6 yearsThis is very expensive on large objects
-
Vidar over 5 yearsShort but slow, and only works for simple values.
-
sgajera over 5 years@Rotareti arrow function will break in IE 11
-
Ankur Loriya over 5 years@Rotareti is this code work with subkeys as well.
-
Thijs Koerselman over 5 yearsThis is a hack more than anything. Formatting code to a string and parsing it back to code just to mutate something that can easily be done programatically? The unintentional side-effects (on Date for example) and computational inefficiency make that this answer should be downvoted IMO.
-
Yulian over 5 yearsKeep in mind that this doesn't work with null values
-
fabb over 5 yearsthis function will modify the passed object, sometimes a nonmutating variant might be desired
-
Anthony Johnston over 4 yearsis it worth checking the property exists first?
key in obj && obj[key] === undefined && delete obj[key]
-
TamusJRoyce over 4 yearsJSON.stringify(value[, replacer[, space]]) - if you use your own replacer, it will work. There is no magic if you understand how the default replacer works. For older browsers, this method may actually be faster for large objects. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
-
TamusJRoyce over 4 yearsPoor coding practice, not using the returned ternary result in the top code. Or the binary shortcut returned Boolean. Same occurs with any C based language including C (excluding optimizer). Just stating my down-vote. *summarized
-
Rotareti over 4 years@TamusJRoyce I agree, I wouldn't use ternary and short-circuit like in the first 2 examples in general. But it's useful in situations in which your code needs to stay declarative. For example, I see this kind of code a lot in React's JSX templates, where it makes sense (IMHO).
-
Vicary over 3 yearsJSON serialization is surprisingly slow. The time scales exponentially, not linearly, with the object size, also good luck with circular references.
-
Nicholas Hamilton over 3 years
Object.keys(obj).reduce((acc, key) => obj[key] === undefined ? {...acc} : {...acc, [key] : obj[key]} , {})
-
dvanoni over 3 yearsThe second argument to
pickBy
defaults toidentity
, so this can be simplified toconst cleanedObject = pickBy(originalObject)
if desired. -
Erwin about 3 yearsJust a warning, the recursive function breaks objects with arrays in them. It needs an additional case to handle arrays.
-
Henrique Bruno over 2 years@Erwin yeah I just had a bug due to this behavior. Have you fixed it? Can you or anyone else edit the answer?
-
Vicary over 2 years
lodash
is way too bloated for any single operations, a project has to heavily and deeply rely on it to justify the bundle size. -1 for encouraging bad practice. -
Thijs Koerselman over 2 yearsOr your code runs on the back-end and you don't worry about bundle size. Or your front-end bundler uses tree shaking and/or rewrites the Lodash imports (Babel plugin) so that you only import what you use. So I don't think it's right to say that Lodash is way too bloated by definition. It depends.
-
Joel Nation about 2 yearsEdited function to allow arrays