9

I am trying to remove null/empty elements from JSON objects, similar to the functionality of the python webutil/util.py -> trim_nulls method. Is there something built in to Node that I can use, or is it a custom method.

Example:

var foo = {a: "val", b: null, c: { a: "child val", b: "sample", c: {}, d: 123 } };

Expected Result:

foo = {a: "val", c: { a: "child val", b: "sample", d: 123 } };
4
  • 1
    You could loop through all the elements and unset them if they are null. Commented Aug 8, 2012 at 23:33
  • 1
    Look at this answer. There is a useful script for you. stackoverflow.com/a/525181/1586177 Commented Aug 8, 2012 at 23:49
  • possible duplicate of null / empty json how to check for it and not output? Commented Aug 9, 2012 at 3:41
  • Do you really mean JSON objects, or do you mean JavaScript objects? Your title and description say JSON, but your example code is JavaScript. Commented Aug 1, 2016 at 13:19

6 Answers 6

5

I don't know why people were upvoting my original answer, it was wrong (guess they just looked too quick, like I did). Anyway, I'm not familiar with node, so I don't know if it includes something for this, but I think you'd need something like this to do it in straight JS:

var remove_empty = function ( target ) {

  Object.keys( target ).map( function ( key ) {

    if ( target[ key ] instanceof Object ) {

      if ( ! Object.keys( target[ key ] ).length && typeof target[ key ].getMonth !== 'function') {

        delete target[ key ];

      }

      else {

        remove_empty( target[ key ] );

      }

    }

    else if ( target[ key ] === null ) {

      delete target[ key ];

    }

  } );


  return target;

};

remove_empty( foo );

I didn't try this with an array in foo -- might need extra logic to handle that differently.

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

Comments

5

You can use this:

let fooText = JSON.stringify(foo);
    
let filteredFoo = JSON.parse(objectLogText, (key, value) => {if(value !== null) return value});

JSON.parse() docs

Comments

4

You can use like this :

Object.keys(foo).forEach(index => (!foo[index] && foo[index] !== undefined) && delete foo[index]);

Comments

3

Thanks for all the help.. I've pieced the following code using the feedback in all of the comments which works with foo.

function trim_nulls(data) {
  var y;
  for (var x in data) {
    y = data[x];
    if (y==="null" || y===null || y==="" || typeof y === "undefined" || (y instanceof Object && Object.keys(y).length == 0)) {
      delete data[x];
    }
    if (y instanceof Object) y = trim_nulls(y);
  }
  return data;
}

2 Comments

That'll remove 0's won't it? Is that intentional?
yeah good point, I'll change the "if (!y" statement to suit. Thanks for pointing that out
2

I found this to be the most elegant way. Also I believe JS-engines are heavily optimized for it.

use built in JSON.stringify(value[, replacer[, space]]) functionality. Docs are here.

Example is in context of retrieving some data from an external API, defining some model accordingly, get the result and chop of everything that couldn't be defined or unwanted:

function chop (obj, cb) {
  const valueBlacklist = [''];
  const keyBlacklist = ['_id', '__v'];

  let res = JSON.stringify(obj, function chopChop (key, value) {
    if (keyBlacklist.indexOf(key) > -1) {
      return undefined;
    }

    // this here checks against the array, but also for undefined
    // and empty array as value
    if (value === null || value === undefined || value.length < 0 || valueBlacklist.indexOf(value) > -1) {
      return undefined;
    }
    return value;
 })
 return cb(res);
}

In your implementation.

// within your route handling you get the raw object `result`
chop(user, function (result) {
   var body = result || '';
   res.writeHead(200, {
      'Content-Length': Buffer.byteLength(body),
      'Content-Type': 'application/json'
   });
   res.write(body);
   // bang! finsihed.
   return res.end();
});

// end of route handling

1 Comment

Nice very elegant, used stringify all the time, never thought of using it this way, nice,
1

You can just filter with a for loop and output to a new clean object:

var cleanFoo = {};
for (var i in foo) {
  if (foo[i] !== null) {
    cleanFoo[i] = foo[i];
  }
}

If you need to process children objects too you'll need recursion.

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.