0

I have tried many different ways to parse and delete keys with empty values dynamically from a JSON file, using only JavaScript.

As of now, I have been able to delete keys that are not nested, with the exception of empty strings with a length greater than 0.

My main ask is how to access subvalues, evaluating the nested keys and deleting only the nested key - right now I end up deleting the root key.

Pardon if this is a duplicated question, but I could not find any implementation for this particular case that worked for me here or elsewhere.

Here is what I have so far:

//DATA
let input = '{"first_name": "","last_name": "Smith","email":"[email protected]","gender": null,"invitations": [{"from": "test","code": ""}],"company": {"name": "dds","industries": [""]},"address": {"city": "New York","state": "NY","zip": "10011","street": " "},"new Value": ""}';



//MAIN FUNCTION
function removeEmptyFields(inputJSON) {
  let data = JSON.parse(inputJSON);

  //accessing top level keys (case1)
  for (let key in data) {
    let item = data[key];
    //dig deeper if value not at top level

    if (item !== null && typeof item !== 'object') {

      deleteRecord(item)
    } else {
      lookDeeper(item)
    }

    if (item === null && typeof item === 'object') {
      deleteRecord(item)
    }



    //function that deletes empty records
    function deleteRecord(item) {
      // console.log(item + "#");//function that deletes empty records
      if (item === null || item === undefined ||
        item.length === 0) {

        delete data[key];
      }

    }

    //function to access values nested one level (case2)

    function lookDeeper(key) {

      if (typeof key === 'object' && typeof key != null) {
        for (let key2 in key) {
          if (typeof key[key2] === 'object' && typeof key[key2] != null) {
            console.log()
            for (let subItem in key[key2]) {
              // deleteRecord(key2[subItem])
            }
          }
          deleteRecord(item[key2])
          lookDeeper(item[key2]);
        }
      }
    }
  }
  return data;
}

let output = removeEmptyFields(input)
console.log(output);

//CASES:
//1-> flat object:
//data[key]
//2 -> array/object
//data[key][array-index]
//3 ->object/object
//data[key][subkey]
//4 ->object/object/array
//data[key][subkey][array-index]


// Test cases in order, and delete nulls at the very end. return data as result

4
  • item === null && typeof item === 'object' thats never true. Commented May 23, 2018 at 17:19
  • Thank you Jonas, I'm going to check the docs on that. Commented May 23, 2018 at 17:20
  • lookDeeper expects a key, you pass a value lookDeeper(item[key2]); Commented May 23, 2018 at 17:20
  • 1
    @JonasW. typeof null is "object" ... Commented May 23, 2018 at 17:25

3 Answers 3

2

Youre actually quite close, if you fix the recursive call and remove all the unneccessary you end up with:

function cleanUp(obj) {
  for(const key in obj) {
    const value = obj[key];
    if(typeof value === "object") {
      cleanUp(value);
    } else if(!value && value !== 0) {
      delete obj[key];
    }
  }
}

let output = JSON.parse(input);
cleanUp(output);
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for taking the time to answer Jonas. My output unfortunately is not what I need. I need for example to have "invitations", "street" and "gender" to be dropped from the output.
What I believe is lacking is a deeper iteration for objects inside keys. Still working on implementing it
0

Found a way to do it. Thanks to everyone who contributed:

//DATA
let input = '{"first_name": "","last_name": "Smith","email":"[email protected]","gender": null,"invitations": [{"from": "test","code": ""}],"company": {"name": "dds","industries": [""]},"address": {"city": "New York","state": "NY","zip": "10011","street": " "},"new Value": ""}';




function isEmpty(value) {
    if (value === null)
        return true;

    if (typeof value == 'object' && Object.keys(value).length === 0)
        return true;

    if (typeof value == 'string' && value.trim() == '')
        return true;

    return false;
}

function removeEmptyFields(input) {
    if (Array.isArray(input)) {
        for (var index = input.length - 1; index >= 0; index--) {
            if (typeof input[index] == 'object') {
                removeEmptyFields(input[index]);
            }
            if (isEmpty(input[index])) {
                input.splice(index, 1);
            }
        }
    } else {
        for (var index in input) {
            if (typeof input[index] == 'object') {
                removeEmptyFields(input[index]);
            }
            if (isEmpty(input[index])) {
                delete input[index];
            }

        }

    }
    return input
}

Comments

0
let input = '{"first_name": "","last_name": "Smith","email":"[email protected]","gender": null,"invitations": [{"from": "test","code": ""}],"company": {"name": "dds","industries": [""]},"address": {"city": "New York","state": "NY","zip": "10011","street": " "},"new Value": ""}'

let objTest = JSON.parse( input )

console.dir( objTest )
purge( objTest )
console.dir( objTest )

/* purge recursively removes empty values from an object
  @param obj the object to purge
  @returns true if the object is an empty value
  */
function purge ( obj ) {
  switch ( true ) {
  case obj === null:
  case typeof obj === 'undefined':
  case typeof obj === 'string' && obj.trim() === '':
    return true

  case Array.isArray( obj ):
    for ( let i = obj.length - 1; i >= 0; i-- ) {
      if ( purge( obj[i] ) ) obj.splice( i, 1 )
    }
    return obj.length === 0

  case typeof obj === 'object':
    Object.keys( obj ).forEach( ( key ) => {
      if ( purge( obj[key] ) ) delete obj[key]
    } )
    return Object.keys( obj ).length === 0

  default:
    return false
  }
}

Comments

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.