Home > Software engineering >  clean up object lead to lost of 0 value
clean up object lead to lost of 0 value

Time:03-08

I came across a list of data operations and lost value of [0].

I could not find out why. it's good if I change value to [1], but if i put value [0], then it's gone.

Here is the code:

let data = {
  title:"hello world",
  value: [0]
}
let sanitized = removeNull(data);
console.log(sanitized)

// ------------------------------------------------------------------------
function removeNull(obj) {
  Object.keys(obj).forEach(k =>
      (obj[k] && typeof obj[k] === 'object') && removeNull(obj[k]) ||
      (typeof obj[k] !== 'boolean' && !obj[k] && obj[k] !== undefined) && delete obj[k]
  );
  return obj;
};

CodePudding user response:

When obj[k] is 0, delete obj[k] is being executed because in the expression:

(obj[k] && typeof obj[k] === 'object') && removeNull(obj[k]) ||
      (typeof obj[k] !== 'boolean' && !obj[k] && obj[k] !== undefined) && delete obj[k]

...obj[k] is falsey (so the entire top line above is false. Then we proceed to check the second line because of the ||.

  • typeof 0 is Number which is !== boolean, so that's true...
  • !0 is truthy...
  • 0 !== undefined is also true...

which leaves us to check the truthiness of the final term which is delete obj[k]. ...which happens to be true by the way, not that it matters, because 0 gets deleted by virtue of us even checking that last term's value.

CodePudding user response:

Some key concepts:

  • 0 is falsey
  • typeof null === 'object' is true
  • typeof [] === 'object' is true

Currently, the code executes as follows:

  • When you get to the part of the loop where obj[k] = [0], removeNull() gets called on [0] because arrays are of type object.
  • When we iterate over [0] in that call of removeNull(), k starts as 0 (the index in the array), and obj[k] becomes 0 (the value). 0 passes typeof 0 !== 'boolean' && !0 && 0 !== undefined, so it gets deleted and turned into an empty item in the array. delete empties out array elements but doesn't remove the index.

There might be some ways to reorganize the code to make it a little safer and easier to debug, depending on whether you want to remove null in arrays, too.

let data = {
  title:"hello world", // not removed
  value: [
    0, // not removed
    null // removed
  ],
  name: null, // removed
  author: {
    name: null, // removed
    hats: false, // not removed
    pets: [null] // --> []
    partners: [] // --> []
  }
}
const sanitized = removeNull(data);
console.log(sanitized)

// -----------------------------------------------------------------------

function removeNull(obj) {
  Object.keys(obj).forEach((key) => {
    if(obj[key] === null) {
      // removes the element differently
      // depending on whether obj is array or object.
      return Array.isArray(obj) ? obj.splice(key, 1) : delete obj[key]
    }
    if(typeof obj[key] === 'object') removeNull(obj[key])
  })
  return obj
}

If you don't care about checking for null in arrays, add && !Array.isArray(obj) to the second check, and remove the ternary that decides how to delete.

One note: in addition to returning the new null-less object, this code (and your code) currently also modify the original object.

CodePudding user response:

Update

Ahhh,typeof obj[k] !== 'boolean' && !obj[k] && obj[k] !== undefined evaluates to true because 0 is considered falsy in Javascript. So !obj[k] is true.

Original answer

The current removeEmpty function is testing if the result of JSON.stringify(o[k] === "[0]") is truthy. You probably meant to test if the stringified contents of o[k] are equal to "[0]". So something like JSON.stringify(o[k]) === "[0]" should solve your problem.

  • Related