How To Deeply Remove Null Values, Empty Objects And Empty Array From An Object
Solution 1:
Here is a function that clean the object recursively. It will loop deeply through all the properties and remove null values, null arrays and null objects:
cleanUpObject(jsonObject: object): object {
Object.keys(jsonObject).forEach(function (key, index) {
const currentObj = jsonObject[key]
if (_.isNull(currentObj)) {
delete jsonObject[key]
} elseif (_.isObject(currentObj)) {
if (_.isArray(currentObj)) {
if (!currentObj.length) {
delete jsonObject[key]
} else {
const cleanupArrayObj = []
for (const obj of currentObj) {
if (!_.isNull(obj)) {
const cleanObj = this.cleanUpJson(obj)
if (!_.isEmpty(cleanObj)) {
cleanupArrayObj.push(cleanObj)
}
}
}
if (!cleanupArrayObj.length) {
delete jsonObject[key]
} else {
jsonObject[key] = cleanupArrayObj
}
}
} else {
if (_.isEmpty(Object.keys(jsonObject[key]))) {
delete jsonObject[key]
} else {
jsonObject[key] = this.cleanUpJson(currentObj)
if (_.isEmpty(Object.keys(jsonObject[key]))) {
delete jsonObject[key]
}
}
}
}
}, this)
return jsonObject
}
Solution 2:
We don't know what you mean by clean, but from what I understand, you want to remove all null and empty values. This algorithm is straight-forward: recursively check for and remove any empty / null values (which are recursively checked).
functionclean(obj) {
// clean arrayif (Array.isArray(obj)) {
for (let i=0; i<obj.length; i++) {
if (isNothing(obj[i])) obj.splice(i, 1); // remove value if falsyelseif (typeof obj[i] === 'object') clean(obj[i]); // recurse if it's a truthy object
}
// clean other object
} else {
for (let prop in obj) {
if (!obj.hasOwnProperty(prop)) continue;
if (isNothing(obj[prop])) delete obj[prop]; // remove value if falsyelseif (typeof obj[prop] === 'object') clean(obj[prop]); // recurse if it's a truthy object
}
}
}
// Recursively check for populated or nonnull content. If none found, return `true`. Recursive so [{}] will be treated as empty.functionisNothing(item) {
// null / undefinedif (item == null) returntrue;
// deep object falsinessif (typeof item === 'object') {
if (Array.isArray(item)) {
// array -> check for populated/nonnull valuefor (let i=0; i<item.length; i++) {
if (!isNothing(item[i])) returnfalse;
}
returntrue;
}
// other object -> check for populated/nonnull valuefor (let prop in item) {
if (!item.hasOwnProperty(prop)) continue;
if (!isNothing(item[prop])) returnfalse;
}
returntrue;
}
returnfalse;
}
var myObject = { a: { b: [{}], c: [{}, {d: 2}], e: 2, f: {} }, g:{}, h:[], i: [null, 2] };
console.log("Before: " + JSON.stringify(myObject));
clean(myObject);
console.log("After: " + JSON.stringify(myObject));
Solution 3:
To reduce repetitive code, one option is to define a function (let's call it itemToBool
) that can determine whether a generic value passed to it is truthy, or recursively truthy somewhere, should the value be an array or object. Then, in the function that gets passed the original object (or, gets recursively passed an object or array), you can call that itemToBool
function whenever there's a value to validate.
In the case of arrays, map
by itemToBool
and then filter
by Boolean. In the case of objects, reduce
the entries
of the object into another object: pass each value of the object through itemToBool
to recursively transform it (in case the value is an array or object), and if the transformed value has any keys (or is a truthy primitive), assign it to the accumulator. No need to depend a library:
var myObject = {
a: {
b: [{}],
c: [{}, {
d: 2
}],
e: 2,
f: {}
},
g: {},
h: [],
i: [null, 2]
};
// Returns a falsey value if the item is falsey,// or if the deep cleaned array or object is empty:constitemToBool = item => {
if (typeof item !== 'object' || item === null) return item;
const cleanedItem = clean(item);
returnObject.keys(cleanedItem).length !== 0 && cleanedItem;
};
constclean = obj => {
if (Array.isArray(obj)) {
const newArr = obj.map(itemToBool).filter(Boolean);
return newArr.length && newArr;
}
const newObj = Object.entries(obj).reduce((a, [key, val]) => {
const newVal = itemToBool(val);
if (newVal) a[key] = newVal;
return a;
}, {});
returnObject.keys(newObj).length > 0 && newObj;
};
console.log(clean(myObject));
Hmm... you also might abstract the check of the number of keys into a function as well:
var myObject={a:{b:[{}],c:[{},{d:2}],e:2,f:{}},g:{},h:[],i:[null,2]}
// Returns the object / array if it has at least one key, else returns false:constvalidObj = obj => Object.keys(obj).length && obj;
constitemToBool = item => (
typeof item !== 'object' || item === null
? item
: validObj(clean(item))
);
constclean = obj => validObj(
Array.isArray(obj)
? obj.map(itemToBool).filter(Boolean)
: Object.entries(obj).reduce((a, [key, val]) => {
const newVal = itemToBool(val);
if (newVal) a[key] = newVal;
return a;
}, {})
);
console.log(clean(myObject));
Post a Comment for "How To Deeply Remove Null Values, Empty Objects And Empty Array From An Object"