Jimi
Jimi

Reputation: 1897

How to remove nested empty objects in JavaScript?

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

Answers (3)

customcommander
customcommander

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

Rohit Kashyap
Rohit Kashyap

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

Taki
Taki

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

Related Questions