Clean object from nulls and undefined - javascript

I've written the following function which cleans nulls and undefined from an object, but for some reason it also removes key where the value is 0.
For example:
{
key1: 'value1',
key2: 0
}
The function will remove key2, even though it should not.
Here is the function:
const cleanJson = function cleanJson (obj) {
if (Object.prototype.toString.call(obj) !== '[object Object]') return obj;
return Object.keys(obj).filter(key => obj[key] && obj[key] !== 'delete').reduce((newObj, key) => {
newObj[key] = Object.prototype.toString.call(obj[key]) !== '[object Object]' ? obj[key] : cleanJson(obj[key]);
return newObj;
}, {});
};
Please advise.

Here is one option using Object.entries:
const myJSON = {key1:'value1', key2:0, key3:null, key4:undefined, key5:""};
const myCleanJSON = Object.entries(myJSON)
.filter(([key, value]) => (value !== null && typeof value !== 'undefined'))
.reduce((acc, b) => ((!acc.length) ? {...acc, [b[0]]: b[1] } : { [acc[0]] : acc[1], [b[0]]: b[1] }));
console.log(myCleanJSON);

The problem is within
obj[key] && obj[key] !== 'delete'
When obj[key] == 0, would return false.

Because 0 (as well as the empty string "") evaluates to false when cast to a Boolean, you need to explicitly check for undefined and null:
let a = {
key1: 'value1',
key2: 0,
key3: null
}
function cleanProps(o) {
if (Object.prototype.toString.call(o) !== '[object Object]') return o
for (key in o) {
if([undefined, null].includes(o[key])) delete o[key]
}
return o
}
console.log(cleanProps(a))

I think that would solve your issue:
obj[key] !== null && obj[key] !== undefined && obj[key] !== 'delete'

Related

How to pass only none null/' ' data to body of fetch update Or to update only none null/' ' data [duplicate]

How do I remove all attributes which are undefined or null in a JavaScript object?
(Question is similar to this one for Arrays)
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;
}, {});
}
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
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)), {});
}
}
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);
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);
}
}
}
JSON.stringify removes the undefined keys.
removeUndefined = function(json){
return JSON.parse(JSON.stringify(json))
}
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
Simplest possible Lodash solution to return an object with the null and undefined values filtered out.
_.omitBy(obj, _.isNil)
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)
You are probably looking for the delete keyword.
var obj = { };
obj.theProperty = 1;
delete obj.theProperty;
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
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)
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()
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)
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
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]}), {})
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
}, {}
)
}
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;
}
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]))
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;
}
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.
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;
}, {});
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;
}, {});
}
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
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);
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;
}, {});
}
With Lodash:
_.omitBy({a: 1, b: null}, (v) => !v)
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 }
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
}, {})
}
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;
}
}

How to iterate an Objects values and replace undefined with null using lodash?

I know how to do this using native Object.entries and a reducer function. But is it possible to replace that with a lodash function?
const object = {
foo: 'bar',
baz: undefined,
}
const nulledObject = Object.entries(object).reduce(
(acc, [key, value]) => ({
...acc,
[key]: typeof value === 'undefined' ? null : value,
}),
{}
);
// {
// foo: 'bar',
// baz: null,
// }
My desire would be something like:
_cloneWith(object, (value) => (typeof value === 'undefined' ? null : value));
I think _.assignWith is what you're looking for:
const nulledObject = _.assignWith({}, object,
(_, value) => typeof value == 'undefined' ? null : value);
I found another solution after posting this question:
const nulledObject = _.mapValues(object,
(value) => (value === undefined ? null : value));

How to Replace null with "-" using single line in Jquery

How to Replace null with - using single line in jQuery
For Example
var obj={
"Key1":null,
"key2":"I have null",
"key3":null
}
Expected Output:
var obj={
"Key1":"-",
"key2":"I have null",
"key3":"-"
}
You could use Object.keys and check the value. with a recursive function with a closure over the iterating object.
var iter = o => k => o[k] && typeof o[k] === 'object' && Object.keys(o[k]).forEach(iter(o[k])) || o[k] === null && (o[k] = '-'),
object = { Key1: null, key2: "I have null", key3: { kje: "test", dfasfd: null, demo: "null demo" } };
Object.keys(object).forEach(iter(object));
console.log(object);
which basically resolves with ES5 in
var object = { Key1: null, key2: "I have null", key3: { kje: "test", dfasfd: null, demo: "null demo" } };
Object.keys(object).forEach(function iter(o) {
return function (k) {
if (o[k] && typeof o[k] === 'object') {
Object.keys(o[k]).forEach(iter(o[k]));
return;
}
o[k] === null && (o[k] = '-');
};
}(object));
console.log(object);
This one-line function will work:
function nullToDash(obj){for(e in obj){if(obj.hasOwnProperty(e) && obj[e]===null){obj[e]="-";}}}
Edit: Unminified above function for better understanding
function nullToDash(obj){
for(e in obj){
if(obj.hasOwnProperty(e) && obj[e]===null){
obj[e]="-";
}
}
}
In one line, It would look something like
JSON.parse(JSON.stringify(obj).split(":null").join((':\"-"')));
var obj = {
"Key1": null,
"key2": "I have null",
"key3": null
}
var obj1=JSON.parse(JSON.stringify(obj).split(":null").join((':\"-"')));
console.log(obj1)
To make the code generic
$.each( obj, function( key, value ) {
if (value == null)
value = "-";
});

Determining if all attributes on a javascript object are null or an empty string

What is the most elegant way to determine if all attributes in a javascript object are either null or the empty string? It should work for an arbitrary number of attributes.
{'a':null, 'b':''} //should return true for this object
{'a':1, 'b':''} //should return false for this object
{'a':0, 'b':1} //should return false
{'a':'', 'b':''} //should return true
Check all values with Object.values. It returns an array with the values, which you can check with Array.prototype.every or Array.prototype.some:
const isEmpty = Object.values(object).every(x => x === null || x === '');
const isEmpty = !Object.values(object).some(x => x !== null && x !== '');
Create a function to loop and check:
function checkProperties(obj) {
for (var key in obj) {
if (obj[key] !== null && obj[key] != "")
return false;
}
return true;
}
var obj = {
x: null,
y: "",
z: 1
}
checkProperties(obj) //returns false
Here's my version, specifically checking for null and empty strings (would be easier to just check for falsy)
function isEmptyObject(o) {
return Object.keys(o).every(function(x) {
return o[x]===''||o[x]===null; // or just "return o[x];" for falsy values
});
}
let obj = { x: null, y: "hello", z: 1 };
let obj1 = { x: null, y: "", z: 0 };
!Object.values(obj).some(v => v);
// false
!Object.values(obj1).some(v => v);
// true
Using Array.some() and check if the values are not null and not empty is more efficient than using Array.every and check it the other way around.
const isEmpty = !Object.values(object).some(x => (x !== null && x !== ''));
This answer should just make the excellent comment of user abd995 more visible.
Quick and simple solution:
Object.values(object).every(value => !!value);
You can use the Array.reduce prototype on your object's keys.
Assuming that the object is structured as follows:
var obj = {
x: null,
y: "",
z: 1
}
you can use the following instruction to discover if all of it's properties are unset or set to empty string using just one line:
Object.keys(obj).reduce((res, k) => res && !(!!obj[k] || obj[k] === false || !isNaN(parseInt(obj[k]))), true) // returns false
If you want to discover if all of it's properties are set instead you have to remove the negation before the conditions and set the initial result value to true only if the object has keys:
Object.keys(obj).reduce((res, k) => res && (!!obj[k] || obj[k] === false || !isNaN(parseInt(obj[k]))), Object.keys(obj).length > 0) // returns false as well
Based on adeneo's answer, I created a single line condition. Hope it will be helpful to someone.
var test = {
"email": "test#test.com",
"phone": "1234567890",
"name": "Test",
"mobile": "9876543210",
"address": {
"street": "",
"city": "",
"state": "",
"country": "",
"postalcode": "r"
},
"website": "www.test.com"
};
if (Object.keys(test.address).every(function(x) { return test.address[x]===''||test.address[x]===null;}) === false) {
console.log('has something');
} else {
console.log('nothing');
}
You can test it https://jsfiddle.net/4uyue8tk/2/
Just complementing the past answers: they'll work if your object doesn't contain arrays or objects. If it does, you'll need to do a 'deep check'.
So I came up with this solution. It'll evaluate the object as empty if all its values (and values inside values) are undefined, {} or [].
function deepCheckEmptyObject(obj) {
return Object.values(obj).every( value => {
if (value === undefined) return true;
else if ((value instanceof Array || value instanceof Object) && _.isEmpty(value) ) return true;
else if (value instanceof Array && !_.isEmpty(value)) return deepCheckEmptyArray(value);
else if (value instanceof Object && !_.isEmpty(value)) return deepCheckEmptyObject(value);
else return false;
});
}
function deepCheckEmptyArray(array) {
return array.every( value => {
if (value === undefined) return true;
else if ((value instanceof Array || value instanceof Object) && _.isEmpty(value)) return true;
else if (value instanceof Array && !_.isEmpty(value)) return deepCheckEmptyArray(value);
else if (value instanceof Object && !_.isEmpty(value)) return deepCheckEmptyObject(value);
else return false;
});
}
Note it uses Lodash's .isEmpty() to do the heavy work after we 'isolated' a value. Here, Lodash is imported as '_'.
Hope it helps!
Also if you are searching for only values are empty within the object,
Object.values({ key: 0, key2: null, key3: undefined, key4: '' }).some(e => Boolean(e))
// false
Object.values({ key: 0, key2: null, key3: undefined, key4: "hello" }).some(e => Boolean(e))
// true
Object.values({ key: 1, key2: "hello" }).some(e => Boolean(e))
// true
Based on tymeJv's answer =)
function checkProperties(obj) {
var state = true;
for (var key in obj) {
if ( !( obj[key] === null || obj[key] === "" ) ) {
state = false;
break;
}
}
return state;
}
var obj = {
x: null,
y: "",
z: 1
}
checkProperties(obj) //returns false
Hope it helps =)
This will give you all the keys from the object which is empty, undefined and null
Object.keys(obj).filter((k)=> {
if (obj[k] === "" || obj[k]===undefined || obj[k]===null) {
return k;
}
});
Building on top of other answers I would use lodash to check isEmpty on the object, as well as its properties.
const isEmpty = (object) => return _.isEmpty(object) || !Object.values(object).some(x => !_.isEmpty(x))
This skip the function attribute
function checkIsNull(obj){
let isNull=true;
for(let key in obj){
if (obj[key] && typeof obj[key] !== 'function') {
isNull = false;
}
}
return isNull;
}
var objectWithFunctionEmpty={
"name":undefined,
"surname":null,
"fun": function (){ alert('ciao'); }
}
var objectWithFunctionFull={
"name":undefined,
"surname":"bla bla",
"fun": function (){ alert('ciao'); }
}
checkIsNull(objectWithFunctionEmpty); //true
checkIsNull(objectWithFunctionFull); //false
This works with me perfectly:
checkProperties(obj) {
let arr = [];
for (let key in obj) {
arr.push(obj[key] !== undefined && obj[key] !== null && obj[key] !== "");
}
return arr.includes(false);
}
This will return true or false if there is at-least one value is empty or something like that.
You can use Object.values() method to get all the object's values (as an array of object's values) and then check if this array of values contains null or "" values, with the help of _.includes method prvided by lodash library.
const checkObjectProperties = obj => {
const objValues = Object.keys(obj);
if (_.includes(objValues, "") || _.includes(objValues, null)) {
return false;
} else {
return true
}
const incorrectObjProps = { one: null, two: "", three: 78 }
const correctObjProps = { one: "some string" }
checkObjectProperties(incorrectObjProps) // return false
checkObjectProperties(correctObjProps) // return true
}
I'll add my two sense:
Object.values(object).every(value => Boolean(value));
Solution:
function checkValues(obj) {
var objValues = Object.values(obj);
if (objValues.length < 1) return false;
return objValues.every((value) => {
if (value === null) return true;
if (typeof(value) == 'string')
if(!(value || false))
return true;
return false;
});
}
// OR
Object.values( obj ).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
);
Testing:
checkValues({ a: null, b: '' });
// OR
Object.values({ a: null, b: '' }).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
);
// Output: true
checkValues({ a: '', b: '' });
// OR
Object.values({ a: '', b: '' }).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
);
// Output: true
checkValues({ a: 0, b: '' });
// OR
Object.values({ a: 0, b: '' }).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
)
// Output: false
checkValues({ a: 0, b: 1 });
// OR
Object.values({ a: 0, b: 1 }).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
)
// Output: false
checkValues({ a: 1, b: '' });
// OR
Object.values({ a: 1, b: '' }).every(
value => value === null || (typeof(value) == 'string' && !(value || false))
)
// Output: false
How about this?
!Object.values(yourObject).join('')

Remove blank attributes from an Object in Javascript

How do I remove all attributes which are undefined or null in a JavaScript object?
(Question is similar to this one for Arrays)
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;
}, {});
}
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
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)), {});
}
}
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);
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);
}
}
}
JSON.stringify removes the undefined keys.
removeUndefined = function(json){
return JSON.parse(JSON.stringify(json))
}
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
Simplest possible Lodash solution to return an object with the null and undefined values filtered out.
_.omitBy(obj, _.isNil)
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)
You are probably looking for the delete keyword.
var obj = { };
obj.theProperty = 1;
delete obj.theProperty;
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
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)
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()
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)
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
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]}), {})
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
}, {}
)
}
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;
}
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]))
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;
}
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.
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;
}, {});
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;
}, {});
}
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
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);
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;
}, {});
}
With Lodash:
_.omitBy({a: 1, b: null}, (v) => !v)
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 }
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
}, {})
}
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;
}
}

Categories

Resources