Steve Davis
Steve Davis

Reputation: 297

Node.js - Remove null elements from JSON object

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

Upvotes: 9

Views: 17716

Answers (6)

You can use this:

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

JSON.parse() docs

Upvotes: 5

Durmuş
Durmuş

Reputation: 76

You can use like this :

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

Upvotes: 4

eljefedelrodeodeljefe
eljefedelrodeodeljefe

Reputation: 6791

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

Upvotes: 2

JMM
JMM

Reputation: 26797

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.

Upvotes: 5

Steve Davis
Steve Davis

Reputation: 297

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

Upvotes: 3

elclanrs
elclanrs

Reputation: 94101

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.

Upvotes: 1

Related Questions