1

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;
1
  • An empty object is not null. So obj[k] != null is going to be true for all keys in stocklevels. Commented Aug 16, 2019 at 21:49

3 Answers 3

4

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>

Sign up to request clarification or add additional context in comments.

Comments

2

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'
  }
}

2 Comments

Using recursion you should be able to remove an empty object at any depth.
for now I only need the upper most level.
0

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));

1 Comment

You can use a recursive approach to check each key if it contains any objects and remove them if empty.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.