[javascript] How do I remove all null and empty string values from an object?

Can you please tell me how to remove all null and empty string values from an object? I am getting an error while deleting the key.

This is what I have so far, but it doesn't work properly:

$.each(sjonObj, function(key, value) {
    if(value == "" || value == null) {
        delete sjonObj.key;
    }
});

_x000D_
_x000D_
var sjonObj= {
  "executionMode": "SEQUENTIAL",
  "coreTEEVersion": "3.3.1.4_RC8",
  "testSuiteId": "yyy",
  "testSuiteFormatVersion": "1.0.0.0",
  "testStatus": "IDLE",
  "reportPath": "",
  "startTime": 0,
  "durationBetweenTestCases": 20,
  "endTime": 0,
  "lastExecutedTestCaseId": 0,
  "repeatCount": 0,
  "retryCount": 0,
  "fixedTimeSyncSupported": false,
  "totalRepeatCount": 0,
  "totalRetryCount": 0,
  "summaryReportRequired": "true",
  "postConditionExecution": "ON_SUCCESS",
  "testCaseList": [
    {
      "executionMode": "SEQUENTIAL",
      "commandList": [
        
      ],
      "testCaseList": [
        
      ],
      "testStatus": "IDLE",
      "boundTimeDurationForExecution": 0,
      "startTime": 0,
      "endTime": 0,
      "label": null,
      "repeatCount": 0,
      "retryCount": 0,
      "totalRepeatCount": 0,
      "totalRetryCount": 0,
      "testCaseId": "a",
      "summaryReportRequired": "false",
      "postConditionExecution": "ON_SUCCESS"
    },
    {
      "executionMode": "SEQUENTIAL",
      "commandList": [
        
      ],
      "testCaseList": [
        {
          "executionMode": "SEQUENTIAL",
          "commandList": [
            {
              "commandParameters": {
                "serverAddress": "www.ggp.com",
                "echoRequestCount": "",
                "sendPacketSize": "",
                "interval": "",
                "ttl": "",
                "addFullDataInReport": "True",
                "maxRTT": "",
                "failOnTargetHostUnreachable": "True",
                "failOnTargetHostUnreachableCount": "",
                "initialDelay": "",
                "commandTimeout": "",
                "testDuration": ""
              },
              "commandName": "Ping",
              "testStatus": "IDLE",
              "label": "",
              "reportFileName": "tc_2-tc_1-cmd_1_Ping",
              "endTime": 0,
              "startTime": 0,
              "repeatCount": 0,
              "retryCount": 0,
              "totalRepeatCount": 0,
              "totalRetryCount": 0,
              "postConditionExecution": "ON_SUCCESS",
              "detailReportRequired": "true",
              "summaryReportRequired": "true"
            }
          ],
          "testCaseList": [
            
          ],
          "testStatus": "IDLE",
          "boundTimeDurationForExecution": 0,
          "startTime": 0,
          "endTime": 0,
          "label": null,
          "repeatCount": 0,
          "retryCount": 0,
          "totalRepeatCount": 0,
          "totalRetryCount": 0,
          "testCaseId": "dd",
          "summaryReportRequired": "false",
          "postConditionExecution": "ON_SUCCESS"
        }
      ],
      "testStatus": "IDLE",
      "boundTimeDurationForExecution": 0,
      "startTime": 0,
      "endTime": 0,
      "label": null,
      "repeatCount": 0,
      "retryCount": 0,
      "totalRepeatCount": 0,
      "totalRetryCount": 0,
      "testCaseId": "b",
      "summaryReportRequired": "false",
      "postConditionExecution": "ON_SUCCESS"
    }
  ]
};

$.each(sjonObj, function(key, value) {
    if(value == "" || value == null) {
        delete sjonObj.key;
    }
});

console.log(sjonObj);
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
_x000D_
_x000D_
_x000D_

This question is related to javascript jquery

The answer is


You need to use the bracket notation because key is a variable holding the key as a value

$.each(sjonObj, function(key,value){
   // console.log(value);
    if(value==""||value==null){
        delete sjonObj[key];
    }

});

delete sjonObj.key deletes the property called key from sjonObj, instead you need to use key as a variable holding the property name.

Note: Still it will not handle the nested objects


Enhancement to Alexis King's code to run without Jquery and removal of empty arrays and array of empty objects (With no properties) recursively.

var sjonObj = {
"executionMode": "SEQUENTIAL",
"coreTEEVersion": "3.3.1.4_RC8",
"testSuiteId": "yyy",
"testSuiteFormatVersion": "1.0.0.0",
"testStatus": "IDLE",
"reportPath": "",
"startTime": 0,
"durationBetweenTestCases": 20,
"endTime": 0,
"lastExecutedTestCaseId": 0,
"repeatCount": 0,
"retryCount": 0,
"fixedTimeSyncSupported": false,
"totalRepeatCount": 0,
"totalRetryCount": 0,
"summaryReportRequired": "true",
"postConditionExecution": "ON_SUCCESS",
"testCaseList": [{
        "executionMode": "SEQUENTIAL",
        "commandList": [{
            "sample1": "",
            "sample2": ""
        }],
        "testCaseList": [

        ],
        "testStatus": "IDLE",
        "boundTimeDurationForExecution": 0,
        "startTime": 0,
        "endTime": 0,
        "label": null,
        "repeatCount": 0,
        "retryCount": 0,
        "totalRepeatCount": 0,
        "totalRetryCount": 0,
        "testCaseId": "a",
        "summaryReportRequired": "false",
        "postConditionExecution": "ON_SUCCESS"
    },
    {
        "executionMode": "SEQUENTIAL",
        "commandList": [

        ],
        "testCaseList": [{
            "executionMode": "SEQUENTIAL",
            "commandList": [{
                "commandParameters": {
                    "serverAddress": "www.ggp.com",
                    "echoRequestCount": "",
                    "sendPacketSize": "",
                    "interval": "",
                    "ttl": "",
                    "addFullDataInReport": "True",
                    "maxRTT": "",
                    "failOnTargetHostUnreachable": "True",
                    "failOnTargetHostUnreachableCount": "",
                    "initialDelay": "",
                    "commandTimeout": "",
                    "testDuration": ""
                },
                "commandName": "Ping",
                "testStatus": "IDLE",
                "label": "",
                "reportFileName": "tc_2-tc_1-cmd_1_Ping",
                "endTime": 0,
                "startTime": 0,
                "repeatCount": 0,
                "retryCount": 0,
                "totalRepeatCount": 0,
                "totalRetryCount": 0,
                "postConditionExecution": "ON_SUCCESS",
                "detailReportRequired": "true",
                "summaryReportRequired": "true"
            }],
            "testCaseList": [

            ],
            "testStatus": "IDLE",
            "boundTimeDurationForExecution": 0,
            "startTime": 0,
            "endTime": 0,
            "label": null,
            "repeatCount": 0,
            "retryCount": 0,
            "totalRepeatCount": 0,
            "totalRetryCount": 0,
            "testCaseId": "dd",
            "summaryReportRequired": "false",
            "postConditionExecution": "ON_SUCCESS"
        }],
        "testStatus": "IDLE",
        "boundTimeDurationForExecution": 0,
        "startTime": 0,
        "endTime": 0,
        "label": null,
        "repeatCount": 0,
        "retryCount": 0,
        "totalRepeatCount": 0,
        "totalRetryCount": 0,
        "testCaseId": "b",
        "summaryReportRequired": "false",
        "postConditionExecution": "ON_SUCCESS"
    }
]};
function filter(obj) {
  for(let key in obj){
    if (obj[key] === "" || obj[key] === null){
        delete obj[key];
    } else if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
            filter(obj[key]);
    } else if (Array.isArray(obj[key])) {
        if(obj[key].length == 0){
            delete obj[key];
        }else{
            for(let _key in obj[key]){
                filter(obj[key][_key]);
            }
            obj[key] = obj[key].filter(value => Object.keys(value).length !== 0);
            if(obj[key].length == 0){
                delete obj[key];
            }
        }
    }   
}};

filter(sjonObj);
console.log(JSON.stringify(sjonObj, null, 3));

function removeAllBlankOrNull(JsonObj) {
    $.each(JsonObj, function(key, value) {
        if (value === "" || value === null) {
            delete JsonObj[key];
        } else if (typeof(value) === "object") {
            JsonObj[key] = removeAllBlankOrNull(value);
        }
    });
    return JsonObj;
}

Deletes all empty strings and null values recursively. Fiddle


_x000D_
_x000D_
var data = [_x000D_
   { "name": "bill", "age": 20 },_x000D_
   { "name": "jhon", "age": 19 },_x000D_
   { "name": "steve", "age": 16 },_x000D_
   { "name": "larry", "age": 22 },_x000D_
   null, null, null_x000D_
];_x000D_
_x000D_
//eliminate all the null values from the data_x000D_
data = data.filter(function(x) { return x !== null }); _x000D_
_x000D_
console.log("data: " + JSON.stringify(data));
_x000D_
_x000D_
_x000D_


Here is the optimized code snippet to remove empty arrays/objects as well:

function removeNullsInObject(obj) {
    if( typeof obj === 'string' ){ return; }
    $.each(obj, function(key, value){
        if (value === "" || value === null){
            delete obj[key];
        } else if ($.isArray(value)) {
            if( value.length === 0 ){ delete obj[key]; return; }
            $.each(value, function (k,v) {
                removeNullsInObject(v);
            });
        } else if (typeof value === 'object') {
            if( Object.keys(value).length === 0 ){ 
                delete obj[key]; return; 
            }
            removeNullsInObject(value);
        }
    }); 
 }

Thanks @Alexis king :)


There is a very simple way to remove NULL values from JSON object. By default JSON object includes NULL values. Following can be used to remove NULL from JSON string

JsonConvert.SerializeObject(yourClassObject, new JsonSerializerSettings() {
                                       NullValueHandling = NullValueHandling.Ignore})) 

Note: this doen't sanitize arrays:

import { isPlainObject } from 'lodash';

export const sanitize = (obj: {}) => {
  if (isPlainObject(obj)) {
    const sanitizedObj = {};

    for (const key in obj) {
      if (obj[key]) {
        sanitizedObj[key] = sanitize(obj[key]);
      }
    }

    return sanitizedObj;
  } else {
    return obj;
  }
};

Test:

  describe('sanitize', () => {
    it('should keep an object if there are no empty fields', () => {
      expect(sanitize({})).toEqual({});
      expect(sanitize({ foo: 'bar' })).toEqual({ foo: 'bar' });
      expect(sanitize({ content: { foo: 'bar' } })).toEqual({
        content: { foo: 'bar' },
      });
    });

    it('should remove empty fields from top level', () => {
      expect(sanitize({ foo: '', bar: 'baz' })).toEqual({ bar: 'baz' });
      expect(sanitize({ foo: null, bar: 'baz' })).toEqual({ bar: 'baz' });
      expect(sanitize({ foo: undefined, bar: 'baz' })).toEqual({ bar: 'baz' });
    });

    it('should remove nested empty fields', () => {
      expect(sanitize({ content: { foo: '', bar: 'baz' } })).toEqual({
        content: { bar: 'baz' },
      });
      expect(sanitize({ content: { foo: null, bar: 'baz' } })).toEqual({
        content: { bar: 'baz' },
      });
      expect(sanitize({ content: { foo: undefined, bar: 'baz' } })).toEqual({
        content: { bar: 'baz' },
      });
    });
  });

Using some ES6 / ES2015:

If you don't like to create an extra function and remove the items 'inline'.

Object.keys(obj).forEach(k => (!obj[k] && obj[k] !== undefined) && delete obj[k]);

jsbin

Same, written as a function.

const removeEmpty = (obj) => {
  Object.keys(obj).forEach((k) => (!obj[k] && obj[k] !== undefined) && delete obj[k]);
  return obj;
};

jsbin

This function uses recursion to delete items from nested objects as well:

const removeEmpty = (obj) => {
  Object.keys(obj).forEach(k =>
    (obj[k] && typeof obj[k] === 'object') && removeEmpty(obj[k]) ||
    (!obj[k] && obj[k] !== undefined) && delete obj[k]
  );
  return obj;
};

jsbin

Same as function before but with ES7 / 2016 Object.entries:

const removeEmpty = (obj) => {
  Object.entries(obj).forEach(([key, val])  =>
    (val && typeof val === 'object') && removeEmpty(val) ||
    (val === null || val === "") && delete obj[key]
  );
  return obj;
};

Same as third example but in plain ES5:

function removeEmpty(obj) {
  Object.keys(obj).forEach(function(key) {
    (obj[key] && typeof obj[key] === 'object') && removeEmpty(obj[key]) ||
    (obj[key] === '' || obj[key] === null) && delete obj[key]
  });
  return obj;
};

jsbin


According to Alexis King answer, here is a plain JavaScript version.

_x000D_
_x000D_
function cleanUp(obj) {_x000D_
    for (var attrKey in obj) {_x000D_
        var attrValue = obj[attrKey];_x000D_
        if (attrValue === null || attrValue === "") {_x000D_
            delete obj[attrKey];_x000D_
        } else if (Object.prototype.toString.call(attrValue) === "[object Object]") {_x000D_
            cleanUp(attrValue);_x000D_
        } else if (Array.isArray(attrValue)) {_x000D_
            attrValue.forEach(function (arrayValue) {_x000D_
                cleanUp(arrayValue);_x000D_
            });_x000D_
        }_x000D_
    }_x000D_
}
_x000D_
_x000D_
_x000D_


_x000D_
_x000D_
const myObject = {
  key1: "Hello",
  key2: null,
  key3: "",
  key4: undefined,
  key5: "World"
};


const filteredObj = obj =>
    Object.entries(obj)
      .filter(([_, value]) => !!value)
      .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
      
      
      
console.log(filteredObj(myObject));
_x000D_
_x000D_
_x000D_


Building upon suryaPavan's answer this slight modification can cleanup the empty object after removing the invidival emptys inside the object or array. this ensures that you don't have an empty array or object hanging around.

function removeNullsInObject(obj) {
            if( typeof obj === 'string' || obj === "" ){
                return;
            }
            $.each(obj, function(key, value){
                if (value === "" || value === null){
                    delete obj[key];
                } else if ($.isArray(value)) {
                    if( value.length === 0 ){
                        delete obj[key];
                        return;
                    }
                    $.each(value, function (k,v) {
                        removeNullsInObject(v);
                    });
                    if( value.length === 0 ){
                        delete obj[key];
                    }
                } else if (typeof value === 'object') {
                    if( Object.keys(value).length === 0 ){
                        delete obj[key];
                        return;
                    }
                    removeNullsInObject(value);
                    if( Object.keys(value).length === 0 ){
                        delete obj[key];
                    }
                }
            });
 }