user125535
user125535

Reputation: 262

recursively delete all JSON keys with null values and delete parent key if all child keys are deleted

I'm trying to recursively delete null values in a JSON object and all Subobjects. If the subobjects keys are all deleted, then I want that subobject to be deleted as well.

ie.

x = {
  "applicant": {
    'first_name': null,
    'last_name': null,
    'employment_type': null
  },
  'phone': 1123123,
  'branch': null,
  'industry': {
    'id': 1,
    'name': null
  },
  "status": "333"
}

should turn into this:

x = {
    'phone': 1123123,
    'industry': {
         "id": 1
     },
     "status": "333"
    }

Here is the function that I wrote to delete all keys with null values:

function delKeys(app){
  for(key in app){
    if(app[key] !== null && typeof(app[key]) === 'object'){
      delKeys(app[key])
    } 
    if(app[key] === null){
      delete app[key]
      }
  }

But this doesn't delete the parent key with no children:

so instead of the result above, I get this:

x = {
    "applicant":{},
    "phone":1123123,
    "industry":{
       'id': 1
     }
     "status": "333"
     }

As you can see, it doesn't delete the applicant key. How would I check for that within the function? or does it need to be written in a separate function that I call AFTER calling delKeys()?

Also, does anyone see this hitting maximum recursion depth? I've tried with bigger JSON objects and it seems to be hitting max recursion depth. I would really appreciate help with debugging that

thank you.

Upvotes: 2

Views: 3393

Answers (4)

Egor Stambakio
Egor Stambakio

Reputation: 18136

There's a simple solution with JSON.parse' reviver function. This function is executed for every element, and if it returns undefined the element is deleted from object. You can check if value is empty and return undefined in this function, and avoid any recursive functions:

const a = {"applicant":{"first_name":null,"last_name":null,"employment_type":null},"phone":1123123,"branch":null,"industry":{"id":1,"name":null},"status":"333"};

const res = JSON.parse(JSON.stringify(a), (k, v) => {
  return (v === null // delete null values
    || (Array.isArray(v) && v.length === 0) // delete empty arrays
    || (typeof v === 'object' && Object.keys(v).length === 0)) // delete empty objects
      ? undefined : v // else return the value
});

console.log(res)

Upvotes: 4

Yury Tarabanko
Yury Tarabanko

Reputation: 45121

You need to check if app[key] has keys after you delete null keys.

const x = {
  "applicant": {
    'first_name': null,
    'last_name': null,
    'employment_type': null
  },
  'phone': 1123123,
  'branch': null,
  'industry': {
    'id': 1,
    'name': null
  },
  "status": "333"
}

function isEmpty(obj) {
  for(var key in obj) return false;

  return true
}

function delKeys(app){
  for(var key in app){
    if(app[key] !== null && typeof(app[key]) === 'object'){
      delKeys(app[key])

      if(isEmpty(app[key])) {
        delete app[key]
      }
    } 
    if(app[key] === null){
      delete app[key]
    }
  }
}

delKeys(x)

console.log(x)

Upvotes: 6

Sudhansu Choudhary
Sudhansu Choudhary

Reputation: 3360

Use Object.keys().length to check if the object is empty or not

function delKeys(app){
  for(key in app){
    if(app[key] !== null && typeof(app[key]) === 'object'){
       //extra check for an empty object.
       if(Object.keys(app[key]).length === 0){
         delete app[key]
       }
       else{
          delKeys(app[key])
       }
    } 
    if(app[key] === null){
      delete app[key]
    }
}

Upvotes: 1

James
James

Reputation: 22247

After

delKeys(app[key]);

you should

delete app[key];

app[key] is an empty object, not === null, so it won't get picked up by the following if block.

Upvotes: 1

Related Questions