509

How do I remove all attributes which are undefined or null in a JavaScript object?

(Question is similar to this one for Arrays)

Community
  • 1
  • 1
abhijit
  • 6,363
  • 5
  • 26
  • 32

54 Answers54

896

ES10/ES2019 examples

A simple one-liner (returning a new object).

let o = Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null));

Same as above but written as a function.

function removeEmpty(obj) {
  return Object.fromEntries(Object.entries(obj).filter(([_, v]) => v != null));
}

This function uses recursion to remove items from nested objects.

function removeEmpty(obj) {
  return Object.fromEntries(
    Object.entries(obj)
      .filter(([_, v]) => v != null)
      .map(([k, v]) => [k, v === Object(v) ? removeEmpty(v) : v])
  );
}

ES6/ES2015 examples

A simple one-liner. Warning: This mutates the given object instead of returning a new one.

Object.keys(obj).forEach((k) => obj[k] == null && delete obj[k]);

A single declaration (not mutating the given object).

let o = Object.keys(obj)
  .filter((k) => obj[k] != null)
  .reduce((a, k) => ({ ...a, [k]: obj[k] }), {});

Same as above but written as a function.

function removeEmpty(obj) {
  return Object.entries(obj)
    .filter(([_, v]) => v != null)
    .reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});
}

This function uses recursion to remove items from nested objects.

function removeEmpty(obj) {
  return Object.entries(obj)
    .filter(([_, v]) => v != null)
    .reduce(
      (acc, [k, v]) => ({ ...acc, [k]: v === Object(v) ? removeEmpty(v) : v }),
      {}
    );
}

Same as the function above, but written in an imperative (non-functional) style.

function removeEmpty(obj) {
  const newObj = {};
  Object.entries(obj).forEach(([k, v]) => {
    if (v === Object(v)) {
      newObj[k] = removeEmpty(v);
    } else if (v != null) {
      newObj[k] = obj[k];
    }
  });
  return newObj;
}

ES5/ES2009 examples

In the old days things were a lot more verbose.

This is a non recursive version written in a functional style.

function removeEmpty(obj) {
  return Object.keys(obj)
    .filter(function (k) {
      return obj[k] != null;
    })
    .reduce(function (acc, k) {
      acc[k] = obj[k];
      return acc;
    }, {});
}

This is a non recursive version written in an imperative style.

function removeEmpty(obj) {
  const newObj = {};
  Object.keys(obj).forEach(function (k) {
    if (obj[k] && typeof obj[k] === "object") {
      newObj[k] = removeEmpty(obj[k]);
    } else if (obj[k] != null) {
      newObj[k] = obj[k];
    }
  });
  return newObj;
}

And a recursive version written in a functional style.

function removeEmpty(obj) {
  return Object.keys(obj)
    .filter(function (k) {
      return obj[k] != null;
    })
    .reduce(function (acc, k) {
      acc[k] = typeof obj[k] === "object" ? removeEmpty(obj[k]) : obj[k];
      return acc;
    }, {});
}
Rotareti
  • 49,483
  • 23
  • 112
  • 108
  • Regarding #5, do you imply *functional* => unreadable? Why using `o` and `k` where in every other example you are using `object` and `key`? – Augustin Riedinger Dec 13 '16 at 15:14
  • 3
    @AugustinRiedinger When I have to decide between a line-break and an abbreviation I sometimes go for the abbreviation if I think the abbreviation is the lesser evil. The code in 5) is not difficult to reason about and it's a function which removes empty `keys` from an `object`, so `o` and `k` are obvious. But I guess it's a matter of taste. – Rotareti Dec 13 '16 at 17:10
  • 3
    First version with a ES5 flavor: `Object.keys(myObj).forEach(function (key) {(myObj[key] == null) && delete myObj[key]});` – Neurotransmitter Mar 01 '17 at 10:14
  • 2
    One line, without function: `Object.entries(myObj).reduce((acc, [key, val]) => { if (val) acc[key] = val; return acc; }, {})` – Paul Slm May 10 '17 at 17:20
  • In #6, `val === null` should be `val == null` (i.e. use the equality operator instead of the identity operator). Likewise, in #7, `obj[key] === null` should be `obj[key] == null`. – Ron Martinez Aug 26 '17 at 02:21
  • 9
    Since we are trying to be thorough, it might be nice to see an immutable solution. These are mutating the source object and are deceivingly returning the object which is actually unnecessary because the object has been mutated. Beginners will capture the returned object value and wonder why their source object is modified too. – Mike McLin Jan 29 '18 at 21:58
  • @MikeMcLin Good point! 5) is already immutable, but I added 4b), which is an imperative approach to 5). I also removed the `return` statement from the functions that mutate the source object. Should be less confusing now. I also removed 2), since it doesn't make sense. – Rotareti Jan 30 '18 at 07:05
  • Same version as 5) but shorter: – Michal Moravcik Aug 23 '18 at 20:07
  • Same version as 5) just shorter: const removeEmpty = (obj) => return Object.keys(obj) .filter(k => obj[k] !== null && obj[k] !== undefined) // Remove undefined and null .reduce((newObj, k) => (newObj[k] = typeof obj[k] === 'object' ? removeEmpty(obj[k]) : obj[k], newObj), {}); – Michal Moravcik Aug 23 '18 at 20:09
  • How i can delete the "father" that have any attributes anymore? for example a object had all of the attributes null so what is the point of mantain the object alive, i want to delete the father if the childs dont exist anymore, how can i? – Paulo Roberto Rosa Nov 28 '18 at 22:13
  • 12
    5) Doesn't work with arrays (Object.keys will return array position numbers as the key for the elements). Possibly others have this problem, but I found this when testing 5. – Eelco Jun 13 '19 at 19:25
  • Case 4 worked for me with a little modification in the else if condition (obj[key] == null || obj[key] == ''). So with this I'm capable of removing items with empty strings (no characters and no spaces). – Williams A. Dec 30 '19 at 12:00
  • 1
    Ugghhhh. I wish i didn't blindly copy one of these. I was going crazy with DynamoDB. Please check for `Array.isArray(obj)` before `typeof obj === 'object'`. Array.isArray(obj) === true and typeof obj === 'object' will both pass. – Will Farley Mar 17 '20 at 14:16
  • 1
    How is it better than `JSON.parse(JSON.stringify(obj, (k,v) => v==null?undefined:v))` as mentioned in https://stackoverflow.com/a/54707141/906265 ? – Ivar Mar 20 '20 at 15:01
  • @Rotareti why reverted the suggestion I made using the new feature for code snippet that Stack allow to execute `javascript` code right way? Was it because the use of `console.log()`? I also fix the [7] because the function has to return the obj `return obj;` – AndyDaSilva52 Dec 15 '20 at 15:57
  • @Rotareti What about when there are only curly braces `{}`??? For example the JSON `{ g: {}, h: "test" }` that has to result `{ h: "test" }` – AndyDaSilva52 Dec 28 '20 at 22:54
  • 2
    For anyone's interested in the nesting-handler code, and in fixing the bug where an array is turned into an object, and in the bonus of removing empty nested objects and arrays, here's an updated code ([tested here](https://jsfiddle.net/c217t6pd/)): `function removeEmpty(obj) { var clean = Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, v === Object(v) ? removeEmpty(v) : v]).filter(([_, v]) => v != null && (v !== Object(v) || Object.keys(v).length))); return Array.isArray(obj) ? Object.values(clean) : clean; }` – OfirD Sep 22 '21 at 16:57
  • @Ivar, JSON utilities (parse and stringify) are really slow. Doing it ones or twice probably won't slow you down very much, but in a large dataset it will begin to show. – Daniel Dec 22 '21 at 23:44
  • ️ https://stackoverflow.com/a/71968391/8621764 check link where you can clear not only null or undefined even you can define your custom value you have to remove ️ https://stackoverflow.com/a/71968391/8621764 – ABHIJEET KHIRE Apr 22 '22 at 12:04
  • @baka-san Why were you using this on arrays? Javascript Array already has a filter method. – rineez Feb 14 '23 at 15:53
  • Build a small tool if you need to simplify your config, or similar https://simplifyjson.com (works purely on client-side) – Leonid Bugaev Jul 22 '23 at 15:25
281

You can loop through the object:

var test = {
  test1: null,
  test2: 'somestring',
  test3: 3,
}

function clean(obj) {
  for (var propName in obj) {
    if (obj[propName] === null || obj[propName] === undefined) {
      delete obj[propName];
    }
  }
  return obj
}

console.log(test);
console.log(clean(test));

If you're concerned about this property removal not running up object's proptype chain, you can also:

function clean(obj) {
  var propNames = Object.getOwnPropertyNames(obj);
  for (var i = 0; i < propNames.length; i++) {
    var propName = propNames[i];
    if (obj[propName] === null || obj[propName] === undefined) {
      delete obj[propName];
    }
  }
}

A few notes on null vs undefined:

test.test1 === null; // true
test.test1 == null; // true

test.notaprop === null; // false
test.notaprop == null; // true

test.notaprop === undefined; // true
test.notaprop == undefined; // true
AndyDaSilva52
  • 115
  • 3
  • 19
Owen
  • 82,995
  • 21
  • 120
  • 115
  • 2
    Added a quick correction. Undeclared "i" variable would leak into outer scope if this snippet were ever used in a function. – Eric Nguyen Dec 16 '13 at 06:11
  • 9
    you can simplify the (test[i]===null || test[i]===undefined) to (test[i]==null) – jaf0 May 24 '15 at 03:01
  • Hi, @EricNguyen, unlike C and other several languages, javascript does *not* have block scope for variables (only function scope), thus, the variable _i_ will always leak into the scope after the _for_ block. – Gerardo Lima May 10 '16 at 09:54
  • 1
    @GerardoLima, yes. I was kind of assuming that this would be all wrapped in a function. What I meant (assuming this is all wrapped with a function) is that you need the var declaration or _i_ will leak even outside of the function scope. – Eric Nguyen May 14 '16 at 02:32
  • This will also loop through the primitive object's prototype - which in most cases is not desired. http://stackoverflow.com/a/2869372/1612318 – Rotareti Aug 07 '16 at 22:26
  • @Rotareti just updated the answer to include one that restricts itself to the object's own properties. – Eric Nguyen Sep 23 '16 at 00:32
  • Can you please take a look at this question: http://stackoverflow.com/questions/42783607/if-value-of-a-property-is-null-when-updating-then-that-property-should-not-be-ad – Vishal Mar 19 '17 at 06:26
  • This approach is nice and clear, not a fan of the brain boggling one liners above. – user115014 Aug 31 '22 at 10:44
220

Shortest one liners for ES6+

Filter all falsy values ( "", 0, false, null, undefined )

Object.entries(obj).reduce((a,[k,v]) => (v ? (a[k]=v, a) : a), {})

Filter null and undefined values:

Object.entries(obj).reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {})

Filter ONLY null

Object.entries(obj).reduce((a,[k,v]) => (v === null ? a : (a[k]=v, a)), {})

Filter ONLY undefined

Object.entries(obj).reduce((a,[k,v]) => (v === undefined ? a : (a[k]=v, a)), {})

Recursive Solutions: Filters null and undefined

For Objects:

const cleanEmpty = obj => Object.entries(obj)
        .map(([k,v])=>[k,v && typeof v === "object" ? cleanEmpty(v) : v])
        .reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {});

For Objects and Arrays:

const cleanEmpty = obj => {
  if (Array.isArray(obj)) { 
    return obj
        .map(v => (v && typeof v === 'object') ? cleanEmpty(v) : v)
        .filter(v => !(v == null)); 
  } else { 
    return Object.entries(obj)
        .map(([k, v]) => [k, v && typeof v === 'object' ? cleanEmpty(v) : v])
        .reduce((a, [k, v]) => (v == null ? a : (a[k]=v, a)), {});
  } 
}
chickens
  • 19,976
  • 6
  • 58
  • 55
  • 21
    This should be the only answer! Each of these snippets will generate a new object where the old one will not be mutated. This is preferable! A little note if you just use `v == null` you will check against `undefined` and `null`. – Megajin Aug 26 '19 at 12:29
  • the `cleanEmpty` recursve solutions will return an empty object `{}` for Date objects – Emmanuel N K May 13 '20 at 04:03
  • A little more legibility in the one liners would make them awesome!! – zardilior Jun 09 '20 at 19:12
  • Works well with TypeScript as well. Object.entries(record).reduce((a: Anything, [k, v]) => (v.length !== 0 ? (a[k] = v, a) : a), {}) where interface Anything { [key: string]: string; } – Alex Nolasco Jul 23 '20 at 01:21
  • Is it possible to remove only null from arrays and not objects ... how to modify it :) . Please help :) – GOXR3PLUS Oct 12 '20 at 11:46
  • 1
    What do you mean @GOXR3PLUS ? removing nulls from arrays is as simple as `arr = arr.filter(v=>v!==null)` – Superole Nov 26 '20 at 07:43
  • @Superole `Well i am trying to modify the above to remove the nulls only from the arrays inside the object` . So i want it to touch only the arrays inside the object and leave simple key value pairs untouched even if the value is null . But if the value is array `[1,2,null,5,null]` to trim the nulls inside the arrays :) – GOXR3PLUS Nov 26 '20 at 11:52
  • @chickens what about [empty object](https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object)? Ex: JSON `{ g: {}, h: "test" }` that results in `{ h: "test" }` – AndyDaSilva52 Dec 28 '20 at 23:06
  • 2
    a,[k,v] => accumulator, key, value – chickens Mar 02 '21 at 04:45
  • GJ! `reduce`, ternary, comma operator, assignment expression, and single letter variable names all in the same statement. – ruohola Jan 21 '22 at 17:07
  • 1
    Would you please provide some explanation on what exactly is happening in the Recursive Solution for Objects and Arrays? – Nima Mar 10 '22 at 08:23
126

If you are using lodash or underscore.js, here is a simple solution:

var obj = {name: 'John', age: null};

var compacted = _.pickBy(obj);

This will only work with lodash 4, pre lodash 4 or underscore.js, use _.pick(obj, _.identity);

River
  • 8,585
  • 14
  • 54
  • 67
Ben
  • 2,962
  • 2
  • 20
  • 26
  • 1
    Brilliant! Thank you! FYI, what was not obvious to me is that you could use it also like this: foo().then(_.pickBy); // filtering out empty results – Maciej Gurban Aug 02 '16 at 20:36
  • 38
    Note that this will not have the desired result if the object contains falsy values such as 0 or empty strings. Then `_.omit(obj, _.isUndefined)` is better. – JHH May 23 '17 at 11:49
  • 13
    @JHH `_.isUndefined` doesn't omit nulls, use `_.omitBy(obj, _.isNil)` to omit both `undefined` and `null` – Lukasz Wiktor Feb 29 '20 at 07:50
  • @LukaszWiktor Correct, the question did ask for undefined or null. – JHH Mar 02 '20 at 09:21
41

If somebody needs a recursive version of Owen's (and Eric's) answer, here it is:

/**
 * Delete all null (or undefined) properties from an object.
 * Set 'recurse' to true if you also want to delete properties in nested objects.
 */
function delete_null_properties(test, recurse) {
    for (var i in test) {
        if (test[i] === null) {
            delete test[i];
        } else if (recurse && typeof test[i] === 'object') {
            delete_null_properties(test[i], recurse);
        }
    }
}
Wumms
  • 8,176
  • 2
  • 19
  • 18
  • After the for loop begins, you should check that the object [`hasOwnProperty`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) using `if(test.hasOwnProperty(i)) { ... }` – Augie Gardner Oct 19 '16 at 06:01
  • @AugieGardner I'm curious why you'd like to check this - please explain it if you like. (Wouldn't it prevent the checking of inherited properties?) – Wumms Oct 19 '16 at 17:32
38

JSON.stringify removes the undefined keys.

removeUndefined = function(json){
  return JSON.parse(JSON.stringify(json))
}
  • This didn't work for me for a deep object, but [Wumm's answer above](http://stackoverflow.com/a/24190282/1203129) did. – Suman Apr 01 '16 at 19:47
  • 1
    If you need ```null``` to be treated as ```undefined``` use the replacement function, for more info refer to this answer: http://stackoverflow.com/questions/286141/remove-blank-attributes-from-an-object-in-javascript/24190282#40517249 – Hooman Askari Jan 30 '17 at 11:12
  • 2
    Just be aware this doesn't remove `null` values. Try: `let a = { b: 1, c: 0, d: false, e: null, f: undefined, g: [], h: {} }` and then `console.log(removeUndefined(a))`. Question was about `undefined` and `null` values. – mayid Dec 18 '19 at 15:45
  • 1
    JSON methods are for json strings and should never be used for javascript objects without proper parsing and checks. – Maciej Kwas Nov 13 '20 at 20:55
  • @MaciejKwas does it make any difference ? Aren't they both the same except that JSON require keys to be in double Quotations – Lint Apr 01 '22 at 14:43
  • 1
    @Lint yes, it does huge difference, actually. Besides of a fact, that you can just simply loose/mismatch your data (JSON can't handle properly dates, Symbols, Typed Arrays etc calling underneath toString() whenever possible) you can encounter js object with circular dependency, see yourself how JSON.stringify behaves in such situations. – Maciej Kwas Apr 03 '22 at 21:37
20

You can use a combination of JSON.stringify, its replacer parameter, and JSON.parse to turn it back into an object. Using this method also means the replacement is done to all nested keys within nested objects.

Example Object

var exampleObject = {
  string: 'value',
  emptyString: '',
  integer: 0,
  nullValue: null,
  array: [1, 2, 3],
  object: {
    string: 'value',
    emptyString: '',
    integer: 0,
    nullValue: null,
    array: [1, 2, 3]
  },
  arrayOfObjects: [
    {
      string: 'value',
      emptyString: '',
      integer: 0,
      nullValue: null,
      array: [1, 2, 3]
    },
    {
      string: 'value',
      emptyString: '',
      integer: 0,
      nullValue: null,
      array: [1, 2, 3]
    }
  ]
};

Replacer Function

function replaceUndefinedOrNull(key, value) {
  if (value === null || value === undefined) {
    return undefined;
  }

  return value;
}

Clean the Object

exampleObject = JSON.stringify(exampleObject, replaceUndefinedOrNull);
exampleObject = JSON.parse(exampleObject);

CodePen example

Alex Mueller
  • 269
  • 3
  • 5
  • For those using typescript or a newer version of node/js this is a shorter version. `const clean = (object: object) => JSON.parse(JSON.stringify(object, (_, value) => value ?? undefined));` – Alexis Tyler Aug 15 '20 at 05:36
  • Wow, this is just the very best so far. Thanks, @AlexMueller – Vixson Apr 26 '22 at 17:15
15

Simplest possible Lodash solution to return an object with the null and undefined values filtered out.

_.omitBy(obj, _.isNil)

JeffD23
  • 8,318
  • 2
  • 32
  • 41
13

You can do a recursive removal in one line using json.stringify's replacer argument

const removeEmptyValues = obj => (
  JSON.parse(JSON.stringify(obj, (k,v) => v ?? undefined))
)

Usage:

removeEmptyValues({a:{x:1,y:null,z:undefined}}) // Returns {a:{x:1}}

As mentioned in Emmanuel's comment, this technique only worked if your data structure contains only data types that can be put into JSON format (strings, numbers, lists, etc).

(This answer has been updated to use the new Nullish Coalescing operator. depending on browser support needs you may want to use this function instead: (k,v) => v!=null ? v : undefined)

Scotty Jamison
  • 10,498
  • 2
  • 24
  • 30
12

You are probably looking for the delete keyword.

var obj = { };
obj.theProperty = 1;
delete obj.theProperty;
Orion Edwards
  • 121,657
  • 64
  • 239
  • 328
yfeldblum
  • 65,165
  • 12
  • 129
  • 169
  • 5
    This is what he is doing above, this also still leaves undefined in the object. – Josh Bedo Jul 24 '14 at 15:54
  • ️ https://stackoverflow.com/a/71968391/8621764 check link where you can clear not only null or undefined even you can define your custom value you have to remove ️ https://stackoverflow.com/a/71968391/8621764 – ABHIJEET KHIRE Apr 22 '22 at 12:03
8

you can do shorter with ! condition

var r = {a: null, b: undefined, c:1};
for(var k in r)
   if(!r[k]) delete r[k];

Remember in usage : as @semicolor announce in comments: This would also delete properties if the value is an empty string, false or zero

nguyên
  • 5,156
  • 5
  • 43
  • 45
8

Remove all the properties with null and undefined

let obj = {
"id": 1,
"firstName": null,
"lastName": null,
"address": undefined,
"role": "customer",
"photo": "fb79fd5d-06c9-4097-8fdc-6cebf73fab26/fc8efe82-2af4-4c81-bde7-8d2f9dd7994a.jpg",
"location": null,
"idNumber": null,
};

   let result =  Object.entries(obj).reduce((a,[k,v]) => (v == null ? a : (a[k]=v, a)), {});
console.log(result)
Zahirul Haque
  • 1,599
  • 17
  • 22
7

Using ramda#pickBy you will remove all null, undefined and false values:

const obj = {a:1, b: undefined, c: null, d: 1}
R.pickBy(R.identity, obj)

As @manroe pointed out, to keep false values use isNil():

const obj = {a:1, b: undefined, c: null, d: 1, e: false}
R.pickBy(v => !R.isNil(v), obj)
Amio.io
  • 20,677
  • 15
  • 82
  • 117
  • 1
    `(v) => !R.isNil(v)` is probably a better choice for OP's question, given that `false` or other falsy values would also be rejected by `R.identity` – manroe May 08 '18 at 19:18
7

I have same scenario in my project and achieved using following method.

It works with all data types, few mentioned above doesn't work with date and empty arrays .

removeEmptyKeysFromObject.js

removeEmptyKeysFromObject(obj) {
   Object.keys(obj).forEach(key => {
  if (Object.prototype.toString.call(obj[key]) === '[object Date]' && (obj[key].toString().length === 0 || obj[key].toString() === 'Invalid Date')) {
    delete obj[key];
  } else if (obj[key] && typeof obj[key] === 'object') {
    this.removeEmptyKeysFromObject(obj[key]);
  } else if (obj[key] == null || obj[key] === '') {
    delete obj[key];
  }

  if (obj[key]
    && typeof obj[key] === 'object'
    && Object.keys(obj[key]).length === 0
    && Object.prototype.toString.call(obj[key]) !== '[object Date]') {
    delete obj[key];
  }
});
  return obj;
}

pass any object to this function removeEmptyKeysFromObject()

bharath muppa
  • 1,070
  • 12
  • 30
6

Shorter ES6 pure solution, convert it to an array, use the filter function and convert it back to an object. Would also be easy to make a function...

Btw. with this .length > 0 i check if there is an empty string / array, so it will remove empty keys.

const MY_OBJECT = { f: 'te', a: [] }

Object.keys(MY_OBJECT)
 .filter(f => !!MY_OBJECT[f] && MY_OBJECT[f].length > 0)
 .reduce((r, i) => { r[i] = MY_OBJECT[i]; return r; }, {});

JS BIN https://jsbin.com/kugoyinora/edit?js,console

Michael J. Zoidl
  • 1,708
  • 16
  • 13
  • 1
    Nice functional solution – puiu May 15 '17 at 16:06
  • I like this! But I think to remove all `null` and `undefined` it would be simpler to just use `MY_OBJECT[f] != null`. Your current solution removes everything but non empty strings/lists and throws an error when values are `null` – Rotareti Jun 13 '17 at 00:53
  • Right, you could also use/chain multiple `filter`'s, would be more readable. – Michael J. Zoidl Jun 13 '17 at 06:27
  • If you generalise this slightly I think you get close to what loadash's `omit` does, you do need to check obj exists before calling `Object.keys`: `const omit = (obj, filter) => obj && Object.keys(obj).filter(key => !filter(obj[key])).reduce((acc,key) => {acc[key] = obj[key]; return acc}, {});` – icc97 Oct 19 '18 at 06:07
  • Nice, but any integer value will be removed with this approach. – Ghis Dec 13 '18 at 15:18
  • This works for [empty object](https://stackoverflow.com/a/32108184/2057854)? Ex JSON `{ f: 'te', a: [], b: {}, c: { c1: {} } }` that should result in `{ f: 'te' }` – AndyDaSilva52 Dec 28 '20 at 23:30
6

Functional and immutable approach, without .filter and without creating more objects than needed

Object.keys(obj).reduce((acc, key) => (obj[key] === undefined ? acc : {...acc, [key]: obj[key]}), {})
peralmq
  • 2,160
  • 1
  • 22
  • 20
  • Very concise answer. To also add the null check just replace `obj[key] === undefined` to `obj[key] === undefined || obj[key] === null` – user3658510 Aug 14 '19 at 17:17
  • a slight variation of the above approach: you can also conditionally spread in the truthy obj property like so ```const omitFalsy = obj => Object.keys(obj).reduce((acc, key) => ({ ...acc, ...(obj[key] && { [key]: obj[key] }) }), {});``` – Kevin K. Sep 13 '19 at 13:50
  • Is `{...acc, [key]: obj[key]}` not a relatively expensive operation in a reduce function, because the keys are copied to a new object each evaluation? Would it not be faster to keep the same object and add the new items to it instead? – Lucas Moeskops Nov 26 '21 at 16:33
5

For a deep search I used the following code, maybe it will be useful for anyone looking at this question (it is not usable for cyclic dependencies ) :

function removeEmptyValues(obj) {
        for (var propName in obj) {
            if (!obj[propName] || obj[propName].length === 0) {
                delete obj[propName];
            } else if (typeof obj[propName] === 'object') {
                removeEmptyValues(obj[propName]);
            }
        }
        return obj;
    }
Daksh M.
  • 4,589
  • 4
  • 30
  • 46
sam
  • 3,441
  • 2
  • 33
  • 42
5

Instead of delete the property, you can also create a new object with the keys that are not null.

const removeEmpty = (obj) => {
  return Object.keys(obj).filter(key => obj[key]).reduce(
    (newObj, key) => {
      newObj[key] = obj[key]
      return newObj
    }, {}
  )
}
Jin Zhao
  • 59
  • 2
  • 2
5

Here is a comprehensive recursive function (originally based on the one by @chickens) that will:

  • recursively remove what you tell it to defaults=[undefined, null, '', NaN]
  • Correctly handle regular objects, arrays and Date objects
const cleanEmpty = function(obj, defaults = [undefined, null, NaN, '']) {
  if (!defaults.length) return obj
  if (defaults.includes(obj)) return

  if (Array.isArray(obj))
    return obj
      .map(v => v && typeof v === 'object' ? cleanEmpty(v, defaults) : v)
      .filter(v => !defaults.includes(v))

  return Object.entries(obj).length 
    ? Object.entries(obj)
        .map(([k, v]) => ([k, v && typeof v === 'object' ? cleanEmpty(v, defaults) : v]))
        .reduce((a, [k, v]) => (defaults.includes(v) ? a : { ...a, [k]: v}), {}) 
    : obj
}

USAGE:

// based off the recursive cleanEmpty function by @chickens. 
// This one can also handle Date objects correctly 
// and has a defaults list for values you want stripped.

const cleanEmpty = function(obj, defaults = [undefined, null, NaN, '']) {
  if (!defaults.length) return obj
  if (defaults.includes(obj)) return

  if (Array.isArray(obj))
    return obj
      .map(v => v && typeof v === 'object' ? cleanEmpty(v, defaults) : v)
      .filter(v => !defaults.includes(v))

  return Object.entries(obj).length 
    ? Object.entries(obj)
        .map(([k, v]) => ([k, v && typeof v === 'object' ? cleanEmpty(v, defaults) : v]))
        .reduce((a, [k, v]) => (defaults.includes(v) ? a : { ...a, [k]: v}), {}) 
    : obj
}


// testing

console.log('testing: undefined \n', cleanEmpty(undefined))
console.log('testing: null \n',cleanEmpty(null))
console.log('testing: NaN \n',cleanEmpty(NaN))
console.log('testing: empty string \n',cleanEmpty(''))
console.log('testing: empty array \n',cleanEmpty([]))
console.log('testing: date object \n',cleanEmpty(new Date(1589339052 * 1000)))
console.log('testing: nested empty arr \n',cleanEmpty({ 1: { 2 :null, 3: [] }}))
console.log('testing: comprehensive obj \n', cleanEmpty({
  a: 5,
  b: 0,
  c: undefined,
  d: {
    e: null,
    f: [{
      a: undefined,
      b: new Date(),
      c: ''
    }]
  },
  g: NaN,
  h: null
}))
console.log('testing: different defaults \n', cleanEmpty({
  a: 5,
  b: 0,
  c: undefined,
  d: {
    e: null,
    f: [{
      a: undefined,
      b: '',
      c: new Date()
    }]
  },
  g: [0, 1, 2, 3, 4],
  h: '',
}, [undefined, null]))
Emmanuel N K
  • 8,710
  • 1
  • 31
  • 37
5

Here's an alternative

Typescript:

function objectDefined <T>(obj: T): T {
  const acc: Partial<T> = {};
  for (const key in obj) {
    if (obj[key] !== undefined) acc[key] = obj[key];
  }
  return acc as T;
}

Javascript:

function objectDefined(obj) {
  const acc = {};
  for (const key in obj) {
    if (obj[key] !== undefined) acc[key] = obj[key];
  }
  return acc;
}
ThomasReggi
  • 55,053
  • 85
  • 237
  • 424
4

To piggypack on Ben's answer on how to solve this problem using lodash's _.pickBy, you can also solve this problem in the sister library: Underscore.js's _.pick.

var obj = {name: 'John', age: null};

var compacted = _.pick(obj, function(value) {
  return value !== null && value !== undefined;
});

See: JSFiddle Example

Community
  • 1
  • 1
Alex Johnson
  • 1,504
  • 13
  • 20
4

If you want 4 lines of a pure ES7 solution:

const clean = e => e instanceof Object ? Object.entries(e).reduce((o, [k, v]) => {
  if (typeof v === 'boolean' || v) o[k] = clean(v);
  return o;
}, e instanceof Array ? [] : {}) : e;

Or if you prefer more readable version:

function filterEmpty(obj, [key, val]) {
  if (typeof val === 'boolean' || val) {
    obj[key] = clean(val)
  };

  return obj;
}

function clean(entry) {
  if (entry instanceof Object) {
    const type = entry instanceof Array ? [] : {};
    const entries = Object.entries(entry);

    return entries.reduce(filterEmpty, type);
  }

  return entry;
}

This will preserve boolean values and it will clean arrays too. It also preserves the original object by returning a cleaned copy.

DaniOcean
  • 596
  • 1
  • 4
  • 8
4

a reduce helper can do the trick (without type checking) -

const cleanObj = Object.entries(objToClean).reduce((acc, [key, value]) => {
      if (value) {
        acc[key] = value;
      }
      return acc;
    }, {});
Yinon
  • 697
  • 7
  • 13
3

With Lodash:

_.omitBy({a: 1, b: null}, (v) => !v)
Dana Woodman
  • 4,148
  • 1
  • 38
  • 35
  • This will remove also 0 or empty string '', better would be ```_.omitBy({a: 1, b: null, c: undefined, d: 0, e: ''}, (v) => typeof v !== undefined && typeof v !== 'null')``` – bukso Mar 29 '21 at 08:44
3

If you don't want to mutate in place, but return a clone with the null/undefined removed, you could use the ES6 reduce function.

// Helper to remove undefined or null properties from an object
function removeEmpty(obj) {
  // Protect against null/undefined object passed in
  return Object.keys(obj || {}).reduce((x, k) => {
    // Check for null or undefined
    if (obj[k] != null) {
      x[k] = obj[k];
    }
    return x;
  }, {});
}
bsyk
  • 1,938
  • 18
  • 20
3

You can also use ... spread syntax using forEach something like this:

let obj = { a: 1, b: "b", c: undefined, d: null };
let cleanObj = {};

Object.keys(obj).forEach(val => {
  const newVal = obj[val];
  cleanObj = newVal ? { ...cleanObj, [val]: newVal } : cleanObj;
});

console.info(cleanObj);
Hardik Pithva
  • 1,729
  • 1
  • 15
  • 31
3

Recursively remove null, undefined, empty objects and empty arrays, returning a copy (ES6 version)

export function skipEmpties(dirty) {
    let item;
    if (Array.isArray(dirty)) {
        item = dirty.map(x => skipEmpties(x)).filter(value => value !== undefined);
        return item.length ? item : undefined;
    } else if (dirty && typeof dirty === 'object') {
        item = {};
        Object.keys(dirty).forEach(key => {
            const value = skipEmpties(dirty[key]);
            if (value !== undefined) {
                item[key] = value;
            }
        });
        return Object.keys(item).length ? item : undefined;
    } else {
        return dirty === null ? undefined : dirty;
    }
}
L. Zampetti
  • 131
  • 1
  • 4
2

If someone needs to remove undefined values from an object with deep search using lodash then here is the code that I'm using. It's quite simple to modify it to remove all empty values (null/undefined).

function omitUndefinedDeep(obj) {
  return _.reduce(obj, function(result, value, key) {
    if (_.isObject(value)) {
      result[key] = omitUndefinedDeep(value);
    }
    else if (!_.isUndefined(value)) {
      result[key] = value;
    }
    return result;
  }, {});
}
Łukasz Jagodziński
  • 3,009
  • 2
  • 25
  • 33
2

If you use eslint and want to avoid tripping the the no-param-reassign rule, you can use Object.assign in conjunction with .reduce and a computed property name for a fairly elegant ES6 solution:

const queryParams = { a: 'a', b: 'b', c: 'c', d: undefined, e: null, f: '', g: 0 };
const cleanParams = Object.keys(queryParams) 
  .filter(key => queryParams[key] != null)
  .reduce((acc, key) => Object.assign(acc, { [key]: queryParams[key] }), {});
// { a: 'a', b: 'b', c: 'c', f: '', g: 0 }
dpmott
  • 282
  • 3
  • 8
2

Here is a functional way to remove nulls from an Object using ES6 without mutating the object using only reduce:

const stripNulls = (obj) => {
  return Object.keys(obj).reduce((acc, current) => {
    if (obj[current] !== null) {
      return { ...acc, [current]: obj[current] }
    }
    return acc
  }, {})
}
Felippe Nardi
  • 615
  • 7
  • 12
  • **Troll comment** Two things regarding this being a functional pattern: within the `stripNulls` function it uses a reference from outside of the accumulator function's scope; and it also mixes the concerns by filtering within the accumulator function. (e.g. `Object.entries(o).filter(([k,v]) => v !== null).reduce((o, [k, v]) => {o[k] = v; return o;}, {});`) *Yes, it will loop over the filtered items twice but the realized perf loss there is negligible.* – Jason Cust Aug 03 '18 at 20:10
2

If you're okay with using Lodash, you can add the DeepDash recursive library and achieve what you want with some pretty concise code:

const prune = obj => _.filterDeep(obj, (v) => !(_.isUndefined(v) || _.isNull(v)));

Calling prune(anObjectWithNulls) will return the object without undefined or null values.

aalaap
  • 4,145
  • 5
  • 52
  • 59
2

Oneliner (Vanilla JS):

let obj = { a: 0, b: "string", c: undefined, d: null };

Object.keys(obj).map(k => obj[k] == undefined ? delete obj[k] : obj[k] );

console.log(obj);

obj will be { a: 0, b: "string" }

ahmelq
  • 593
  • 7
  • 11
2

// basic object you have to clean 
// ️  input _object
const _object = {
    a: null,
    b: undefined,
    email: 'email@test.com',
    mob:88888888888,
    add:""
  };
  
// kays you have to remove having values included in array 
  const  CLEANER_VALUES = [null, undefined, '']
  
// function to clean object pass the raw object and value format you have to clean
  const objectCleaner = (_object, _CLEANER_VALUES = CLEANER_VALUES) =>{
    const cleanedObj = {..._object};
    Object.keys(cleanedObj).forEach(key => {
    if (_CLEANER_VALUES.includes(cleanedObj[key])) {
      delete cleanedObj[key];
    }});
    
    return cleanedObj;
  
  }
  
  // calling function 
  const __cleandedObject = objectCleaner(_object, CLEANER_VALUES);
  console.log('yup you have cleaned object', __cleandedObject); 
  // ️  output { email: "email@test.com",mob: 88888888888 }

  
ABHIJEET KHIRE
  • 2,037
  • 17
  • 10
1

Clean object in place

// General cleanObj function
const cleanObj = (valsToRemoveArr, obj) => {
   Object.keys(obj).forEach( (key) =>
      if (valsToRemoveArr.includes(obj[key])){
         delete obj[key]
      }
   })
}

cleanObj([undefined, null], obj)

Pure function

const getObjWithoutVals = (dontReturnValsArr, obj) => {
    const cleanObj = {}
    Object.entries(obj).forEach( ([key, val]) => {
        if(!dontReturnValsArr.includes(val)){
            cleanObj[key]= val
        } 
    })
    return cleanObj
}

//To get a new object without `null` or `undefined` run: 
const nonEmptyObj = getObjWithoutVals([undefined, null], obj)
Ben Carp
  • 24,214
  • 9
  • 60
  • 72
1

If you don't want to modify the original object (using some ES6 operators):

const keys = Object.keys(objectWithNulls).filter(key => objectWithNulls[key]);
const pairs = keys.map(key => ({ [key]: objectWithNulls[key] }));

const objectWithoutNulls = pairs.reduce((val, acc) => ({ ...val, ...acc }));

The filter(key => objectWithNulls[key])returns anything that is truthy, so will reject any values such as0 or false, as well as undefined or null. Can be easily changed to filter(key => objectWithNulls[key] !== undefined)or something similar if this is unwanted behaviour.

lewtur
  • 603
  • 1
  • 6
  • 16
1

We can use JSON.stringify and JSON.parse to remove blank attributes from an object.

jsObject = JSON.parse(JSON.stringify(jsObject), (key, value) => {
               if (value == null || value == '' || value == [] || value == {})
                   return undefined;
               return value;
           });
Vardaman PK
  • 313
  • 2
  • 7
  • This trick is actually valid, as long as you ensure that the Obj is JSON-serializable. And it works deep as well. – Polv Jan 05 '20 at 09:27
  • Invalid array and object comparison (`{} != {}` and `[] != []`), but otherwise approach is valid – Ivar Mar 20 '20 at 14:56
1
ES6 arrow function and ternary operator:
Object.entries(obj).reduce((acc, entry) => {
   const [key, value] = entry
  if (value !== undefined) acc[key] = value;
  return acc;
}, {})
    const obj = {test:undefined, test1:1 ,test12:0, test123:false};
    const newObj = Object.entries(obj).reduce((acc, entry) => {
       const [key, value] = entry
      if (value !== undefined) acc[key] = value;
      return acc;
    }, {})
    console.log(newObj)
Arturo Montoya
  • 361
  • 3
  • 4
1

remove empty field object

for (const objectKey of Object.keys(data)) {
      if (data[objectKey] === null || data[objectKey] === '' || data[objectKey] === 'null' || data[objectKey] === undefined) {
        delete data[objectKey];
      }
    }
1

This question has been thoroughly answered already, i'd just like to contribute my version based on other examples given:

function filterObject(obj, filter) {
    return Object.entries(obj)
        .map(([key, value]) => {
            return [key, value && typeof value === 'object'
                ? filterObject(value, filter)
                : value];
        })
        .reduce((acc, [key, value]) => {
            if (!filter.includes(value)) {
                acc[key] = value;
            }

            return acc;
        }, {});
}

What makes this solution different is the ability to specify which values you'd like to filter in the second parameter like this:

const filtered = filterObject(originalObject, [null, '']);

Which will return a new object (does not mutate the original object) not including the properties with a value of null or ''.

Shikyo
  • 1,430
  • 1
  • 14
  • 25
1
function filterObject(obj) {
    for (var propName in obj) {
        if (!(obj[propName] || obj[propName] === false)) {
            delete obj[propName];
        }
    }

    return obj;
}

This function also removes NaN value from an object and easy to understand

Aziza Kasenova
  • 1,501
  • 2
  • 10
  • 22
Harsh Soni
  • 49
  • 4
1

Using Nullish coalescing available ES2020

const filterNullishPropertiesFromObject = (obj) => {
  const newEntries = Object.entries(obj).filter(([_, value]) => {
    const nullish = value ?? null;
    return nullish !== null;
  });

  return Object.fromEntries(newEntries);
};
1

You can do this using the nullish coalescing operator: ?? since that checks only for null and undefined values. Note that the example below changes obj itself. It also deletes null and undefined values of nested objects.

const removeEmptyKeys = (obj) => {
    Object.entries(obj).forEach(([k, v]) => {
        (v ?? delete obj[k])
        if (v && typeof v === 'object') {
            removeEmptyKeys(v)
        }
    })
}
Koen Peters
  • 12,798
  • 6
  • 36
  • 59
1

Here is a super clean Typescript solution using reduce:

const removeUndefinedFields = <T>(obj: T): T =>
  Object.keys(obj).reduce(
    (acc, key) =>
      obj[key as keyof T] === undefined
        ? { ...acc }
        : { ...acc, [key]: obj[key as keyof T] },
    {} as T
  )
Baptiste Arnaud
  • 2,522
  • 3
  • 25
  • 55
1

Here's recursive ES6 implementation that cleans up properties of the properties as well. It's a side-effect free function meaning that it does not modify the object so the return object must be used.

function removeUndefinedProperties(obj) {
  return Object.keys(obj || {})
    .reduce((acc, key) => {
      const value = obj[key];
      switch (typeof value) {
        case 'object': {
          const cleanValue = removeUndefinedProperties(value); // recurse
          if (!Object.keys(cleanValue).length) {
            return { ...acc };
          }
          return { ...acc, [key]: cleanValue };
        }
        case 'undefined':
          return { ...acc };
        default:
          return { ...acc, [key]: value };
      }
    }, {});
}

In TypeScript, type it using unknown such as:

function removeUndefinedProperties(obj: unknown): unknown {
  return Object.keys(obj ?? {})
    .reduce((acc, key) => {
      const value = obj[key];
      switch (typeof value) {
        case 'object': {
          const cleanValue = removeUndefinedProperties(value); // recurse
          if (!Object.keys(cleanValue).length) {
            return { ...acc };
          }
          return { ...acc, [key]: cleanValue };
        }
        case 'undefined':
          return { ...acc };
        default:
          return { ...acc, [key]: value };
      }
    }, {});
}
U. Bulle
  • 1,075
  • 9
  • 20
1

Cleans empty array, empty object, empty string, undefined, NaN and null values.

function objCleanUp(obj:any) {
  for (var attrKey in obj) {
    var attrValue = obj[attrKey];
    if (attrValue === null || attrValue === undefined || attrValue === "" || attrValue !== attrValue) {
      delete obj[attrKey];
    } else if (Object.prototype.toString.call(attrValue) === "[object Object]") {
      objCleanUp(attrValue);
      if(Object.keys(attrValue).length===0)delete obj[attrKey];
    } else if (Array.isArray(attrValue)) {
      attrValue.forEach(function (v,index) {
        objCleanUp(v);
        if(Object.keys(v).length===0)attrValue.splice(index,1);
      });
      if(attrValue.length===0)delete obj[attrKey];
    }
  }
}

objCleanUp(myObject)

(attrValue !== attrValue) checks for NaN. Learned it here

prakhar tomar
  • 933
  • 1
  • 8
  • 10
1

var testObject = {
  test1: "null",
  test2: null,
  test3: 'somestring',
  test4: 3,
  test5: "undefined",
  test6: undefined,
}

function removeObjectItem(obj){
  for (var key in obj) {
    if (String(obj[key]) === "null" || String(obj[key]) === "undefined") {
      delete obj[key];
    }
  }
  return obj
}
console.log(removeObjectItem(testObject))
1

A generic function with TypeScript

function cleanProps(object:Record<string, string>):Record<string, string> {
  let cleanObj = {};

  Object.keys(object).forEach((key) => {
    const property = object[key];
    cleanObj = property ? { ...cleanObj, [key]: property } : cleanObj;
  });

  return cleanObj;
}

export default cleanProps;

now lets say you have a object like the following

interface Filters{
 searchString: string;
 location: string;
 sector: string
}

const filters:Filters = {
  searchString: 'cute cats',
  location: '',
  sector: 'education',
};

You can use the function as following

const result = cleanProps(filters as Record<keyof Filters, string>);
console.log(result); // outputs: { searchString: 'cute cats', sector: 'education' }

Nivethan
  • 2,339
  • 19
  • 22
1

This could be solved using Recursion. JavaScript objects could be an array and could have array with null values as a value.

function removeNullValues(obj) {
  // Check weather obj is an array
  if (Array.isArray(obj)) {
    // Creating copy of obj so that index is maintained after splice
    obj.slice(0).forEach((val) => {
      if (val === null) {
        obj.splice(obj.indexOf(val), 1);
      } else if (typeof val === 'object') {
        // Check if array has an object
        removeNullValues(val);
      }
    });
  } else if (typeof obj === 'object') {
    // Check for object
    Object.keys(obj).forEach((key) => {
      if (obj[key] === null) {
        delete obj[key];
      } else if (typeof obj[key] === 'object') {
        removeNullValues(obj[key]);
      }
    });
  }
  return obj;
}
Yash Mehta
  • 31
  • 6
1

There are many valid answers, I was able to solve using a for...in inside add coalescing operator which allows me to know if it is null or undefined to eliminate it

 const test = {
    test1: null,
    test2: "somestring",
    test3: 3,
    test4: undefined
  };

  const clean = (obj) => {
    for (let propName in obj) obj[propName] ?? delete obj[propName];
    return obj;
  };

  console.log(clean(test));
Jackson Quintero
  • 178
  • 1
  • 1
  • 8
1

My way to go for removing undefined properties from an object

TYPESCRIPT
Object.keys(data).forEach((k) => !(data as any)[k] && delete (data as any)[k]);

JAVASCRIPT
Object.keys(data).forEach((k) => !data[k] && delete data[k]);

Cleaner and shorter version of this answer.

Gabriel Arghire
  • 1,992
  • 1
  • 21
  • 34
0

If you prefer the pure/functional approach

const stripUndef = obj => 
  Object.keys(obj)
   .reduce((p, c) => ({ ...p, ...(x[c] === undefined ? { } : { [c]: x[c] })}), {});
Peter Aron Zentai
  • 11,482
  • 5
  • 41
  • 71
0

If you just want to remove undefined top-level properties from an object, I find this to be the easiest:

const someObject = {
  a: null,
  b: 'someString',
  c: 3,
  d: undefined
};

for (let [key, value] of Object.entries(someObject)) {
  if (value === null || value === undefined) delete someObject[key];
}

console.log('Sanitized', someObject);
Benny Code
  • 51,456
  • 28
  • 233
  • 198
-1

30+ answers but I didn't see this short ES6 one-liner, utilizing the spread operator thanks to Object.assign() being a vararg function that silently ignores any non-objects (like false).

Object.assign({}, ...Object.entries(obj).map(([k,v]) => v != null && {[k]: v]))
JHH
  • 8,567
  • 8
  • 47
  • 91
-1

Here's my version of chiken's function

This will remove empty strings, undefined, null from object or object arrays and don't affect Date objects

const removeEmpty = obj => {
   if (Array.isArray(obj)) {
      return obj.map(v => (v && !(v instanceof Date) && typeof v === 'object' ? removeEmpty(v) : v)).filter(v => v)
    } else {
      return Object.entries(obj)
        .map(([k, v]) => [k, v && !(v instanceof Date) && typeof v === 'object' ? removeEmpty(v) : v])
        .reduce((a, [k, v]) => (typeof v !== 'boolean' && !v ? a : ((a[k] = v), a)), {})
    }
  }
Guilherme Nimer
  • 555
  • 2
  • 14