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; }
});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": "", "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);<script src=""></script> 1 13 Answers
You're deleting sjonObj.key, literally. You need to use array access notation:
delete sjonObj[key];However, that will also delete where value is equal to 0, since you're not using strict comparison. Use === instead:
$.each(sjonObj, function(key, value){ if (value === "" || value === null){ delete sjonObj[key]; }
});However, this will only walk the object shallowly. To do it deeply, you can use recursion:
(function filter(obj) { $.each(obj, function(key, value){ if (value === "" || value === null){ delete obj[key]; } else if (Object.prototype.toString.call(value) === '[object Object]') { filter(value); } else if ($.isArray(value)) { $.each(value, function (k,v) { filter(v); }); } });
})(sjonObj);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": "", "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) { $.each(obj, function(key, value){ if (value === "" || value === null){ delete obj[key]; } else if (Object.prototype.toString.call(value) === '[object Object]') { filter(value); } else if (Array.isArray(value)) { value.forEach(function (el) { filter(el); }); } });
})(sjonObj);
console.log(sjonObj)<script src=""></script>Note that if you're willing to use a library like lodash/underscore.js, you can use _.pick instead. However, you will still need to use recursion to filter deeply, since neither library provides a deep filter function.
sjonObj = (function filter(obj) { var filtered = _.pick(obj, function (v) { return v !== '' && v !== null; }); return _.cloneDeep(filtered, function (v) { return v !== filtered && _.isPlainObject(v) ? filter(v) : undefined; });
})(sjonObj);This variant has the added advantage of leaving the original object unmodified, but it does create an entirely new copy, which would be less efficient if you don't need the original object.
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": "", "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" } ]
};
sjonObj = (function filter(obj) { var filtered = _.pick(obj, function (v) { return v !== '' && v !== null; }); return _.cloneDeep(filtered, function (v) { return v !== filtered && _.isPlainObject(v) ? filter(v) : undefined; });
})(sjonObj);
console.log(sjonObj);<script src="//"></script> 3 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]);Same, written as a function.
const removeEmpty = (obj) => { Object.keys(obj).forEach((k) => (!obj[k] && obj[k] !== undefined) && delete obj[k]); return obj;
};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;
};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;
}; 5 var data = [ { "name": "bill", "age": 20 }, { "name": "jhon", "age": 19 }, { "name": "steve", "age": 16 }, { "name": "larry", "age": 22 }, null, null, null
];
//eliminate all the null values from the data
data = data.filter(function(x) { return x !== null });
console.log("data: " + JSON.stringify(data)); 3 I would make use of the JSON parse reviver parameter to remove empty or null from nested objects.
const test = { a: 0, b: null, c: '', d: { e: 1, f: null }, g: { h: null } }
const check = JSON.parse(JSON.stringify(test),
(key, value) => value === null || value === '' ? undefined : value);
console.log(check) 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 :)
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]; } } }); } According to Alexis King answer, here is a plain JavaScript version.
function cleanUp(obj) { for (var attrKey in obj) { var attrValue = obj[attrKey]; if (attrValue === null || attrValue === "") { delete obj[attrKey]; } else if (Object.prototype.toString.call(attrValue) === "[object Object]") { cleanUp(attrValue); } else if (Array.isArray(attrValue)) { attrValue.forEach(function (arrayValue) { cleanUp(arrayValue); }); } }
} const myObject = { key1: "Hello", key2: null, key3: "", key4: undefined, key5: "World", key6: false, key7: true
};
const filteredObj = (obj) => Object.entries(obj) .filter(([_, value]) => !!value || typeof value === "boolean") .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
console.log(filteredObj(myObject)); 2 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
0function 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
0Enhancement 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": "", "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)); 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' }, }); }); }); 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})) 1