Reputation: 1897
I'm wanting to remove empty objects from a nested JSON. I've check a fair few answers on SA but none of them are doing what I need. any assistance is appreciated. I thought that I might be able to reduce the object which is working but I had to do this Object.keys(obj || {})
to stop Object.keys throwing type errors on undefined objects. I'm just wanting to remove any objects that are empty {} and return the objects with values.
Thanks in advance. Jimi
!--- sample object
export const stocklevels = {
coats: {
browncoat: ["L", "M", "S"]
},
neclace: {},
earrings: {
diamond: "Y",
ruby: "Y"
},
shoes: {},
bags: {}
};
!--- function
let newObj = Object.keys(obj || {}).reduce((x, k) => {
if (obj[k] != null) {
x[k] = obj[k];
}
return x;
}, {});
return newObj;
Upvotes: 0
Views: 2236
Reputation: 18901
I would do this using a recursive function that reconstruct an object from its filtered entries:
const clean = obj =>
Object.fromEntries(
Object.entries(obj).flatMap(([k, v]) =>
String(v) !== '[object Object]' ? [[k, v]] :
(v = clean(v), Object.keys(v).length > 0 ? [[k, v]] :
[])));
console.log(clean(sample1));
console.log(clean(sample2));
<script>
const sample1 =
{ coats:
{ browncoat:
["L", "M", "S"] },
neclace:
{},
earrings:
{ diamond: "Y",
ruby: "Y" },
shoes:
{},
bags:
{} };
const sample2 =
{ a:
{ b:
{ c:
{} }},
d:
{ x : 'x' }};
</script>
Upvotes: 4
Reputation: 1592
A simpler implementation: (Not meant for nested objects)
const stocklevels = {
coats: {
browncoat: ["L", "M", "S"]
},
neclace: {},
earrings: {
diamond: "Y",
ruby: "Y"
},
shoes: {},
bags: {}
};
function removeEmpty(obj) {
for(var key in obj) {
if(typeof obj[key] === 'object') {
if(Object.keys(obj[key]).length === 0) {
delete obj[key];
}
}
}
return obj;
}
console.log(removeEmpty(stocklevels));
Upvotes: 0
Reputation: 17654
instead of checking for null
( obj[k] != null
) , check for Object.values().length
( or Object.keys().length
) :
const stocklevels = {
coats: {
browncoat: ["L", "M", "S"]
},
neclace: {},
earrings: {
diamond: "Y",
ruby: "Y"
},
shoes: {},
bags: {}
};
let newObj = Object.keys(stocklevels).reduce((acc, curr) => {
if(Object.keys(stocklevels[curr]).length > 0)
acc[curr] = stocklevels[curr]
return acc;
}, {});
console.log(newObj);
Note that this won't work with nested objects like
const obj ={
a :{
b :{
c :{} // won't remove this
}
},
d : {
x : 'x'
}
}
Upvotes: 2