Javascript - removing undefined fields from an object

176,015

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 to null 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.

Share:
176,015

Related videos on Youtube

Damian
Author by

Damian

Updated on December 19, 2021

Comments

  • Damian
    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
      Amadan over 9 years
      What is your question? Your solutions already do what you want (destructively and nondestructively, respectively).
    • Abdul Jabbar
      Abdul Jabbar over 9 years
      How much more cleaner do you want it to be, it is already clean!
    • sean
      sean about 8 years
      I would use just _.filter(obj, function(v) { return _.isUndefined(v)})
    • Noel Llevares
      Noel Llevares about 7 years
      I wonder which of these answers is the fastest?
    • Andreas Warberg
      Andreas Warberg almost 6 years
      Your omit example simplifies to _.omit(obj, _.isUndefined) (Underscore only)
    • Ryan Allen
      Ryan Allen about 2 years
      With lodash: _.omitBy(obj, _.isUndefined)
  • jfriend00
    jfriend00 over 9 years
    Except Object.keys() has it's own overhead in creating an entire array of the keys and it requires at least IE 9.
  • Matt Langlois
    Matt Langlois almost 8 years
    You 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
    Rotareti almost 8 years
    Even better! I updated the answer. Thanks for mentioning it :)
  • ptim
    ptim over 7 years
    btw, I'm aliasing _acc to avoid the eslint error no-param-reassign
  • Glenn Plas
    Glenn Plas almost 7 years
    this will replace the undefined with null and the entries are still there.
  • nmanikiran
    nmanikiran almost 7 years
    @GlennPlas add a plnkr plnkr.co/edit/wP37G6BA5uJPSFz6xLTq?p=preview check browser console for output
  • Glenn Plas
    Glenn Plas almost 7 years
    Indeed, 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
    Glenn Plas almost 7 years
    Actually, 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
    pandark about 6 years
    !obj[key] will not only remove null, '' and undefined, but also remove 0 and NaN.
  • David
    David almost 6 years
    I started using the filter + forEach and ended up transforming it to a reduce like this. +1
  • sowdri
    sowdri almost 6 years
    Guys, this might look simple, but date objects will be converted to string. Beware
  • CertainPerformance
    CertainPerformance almost 6 years
    SO 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 use if/else.
  • Rotareti
    Rotareti almost 6 years
    @CertainPerformance Fair point. I added an example using an if expression.
  • Kmaid
    Kmaid almost 6 years
    This is very expensive on large objects
  • Vidar
    Vidar over 5 years
    Short but slow, and only works for simple values.
  • sgajera
    sgajera over 5 years
    @Rotareti arrow function will break in IE 11
  • Ankur Loriya
    Ankur Loriya over 5 years
    @Rotareti is this code work with subkeys as well.
  • Thijs Koerselman
    Thijs Koerselman over 5 years
    This 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
    Yulian over 5 years
    Keep in mind that this doesn't work with null values
  • fabb
    fabb over 5 years
    this function will modify the passed object, sometimes a nonmutating variant might be desired
  • Anthony Johnston
    Anthony Johnston over 4 years
    is it worth checking the property exists first? key in obj && obj[key] === undefined && delete obj[key]
  • TamusJRoyce
    TamusJRoyce over 4 years
    JSON.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
    TamusJRoyce over 4 years
    Poor 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
    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
    Vicary over 3 years
    JSON serialization is surprisingly slow. The time scales exponentially, not linearly, with the object size, also good luck with circular references.
  • Nicholas Hamilton
    Nicholas Hamilton over 3 years
    Object.keys(obj).reduce((acc, key) => obj[key] === undefined ? {...acc} : {...acc, [key] : obj[key]} , {})
  • dvanoni
    dvanoni over 3 years
    The second argument to pickBy defaults to identity, so this can be simplified to const cleanedObject = pickBy(originalObject) if desired.
  • Erwin
    Erwin about 3 years
    Just a warning, the recursive function breaks objects with arrays in them. It needs an additional case to handle arrays.
  • Henrique Bruno
    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
    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
    Thijs Koerselman over 2 years
    Or 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
    Joel Nation about 2 years
    Edited function to allow arrays