{"ScriptPreparationCode":"var isPlainObject = (value) =\u003E value !== null \u0026\u0026 typeof value === \u0027object\u0027 \u0026\u0026 !Array.isArray(value);\r\nvar isEmpty = (value) =\u003E {\r\n return (value === undefined ||\r\n value === null ||\r\n value === \u0027\u0027 ||\r\n (typeof value === \u0027object\u0027 \u0026\u0026 Object.keys(value).length === 0));\r\n};\r\n\r\nvar cleanObjectFromEmptyData1 = (obj, allowEmpty, deleteEmptyValues = false) =\u003E {\r\n const result = {};\r\n for (const [key, value] of Object.entries(obj)) {\r\n if (allowEmpty === null || allowEmpty === void 0 ? void 0 : allowEmpty.includes(key)) {\r\n result[key] = value;\r\n continue;\r\n }\r\n if (value === undefined) {\r\n continue;\r\n }\r\n if (isPlainObject(value)) {\r\n const cleanedValue = cleanObjectFromEmptyData1(value, allowEmpty, deleteEmptyValues);\r\n if (!isEmpty(cleanedValue)) {\r\n result[key] = cleanedValue;\r\n }\r\n continue;\r\n }\r\n if (Array.isArray(value)) {\r\n const cleanedArray = value\r\n .map((item) =\u003E (isPlainObject(item) ? cleanObjectFromEmptyData1(item, allowEmpty, deleteEmptyValues) : item))\r\n .filter((item) =\u003E !isEmpty(item));\r\n if (cleanedArray.length \u003E 0 || !deleteEmptyValues) {\r\n result[key] = cleanedArray;\r\n }\r\n continue;\r\n }\r\n if (!deleteEmptyValues || !isEmpty(value)) {\r\n result[key] = value;\r\n }\r\n }\r\n return result;\r\n};\r\n\r\n\r\nvar cleanObjectFromEmptyData2 = (obj, allowEmpty, deleteEmptyValues = false) =\u003E {\r\n return Object.entries(obj).reduce((acc, [key, value]) =\u003E {\r\n if (allowEmpty === null || allowEmpty === void 0 ? void 0 : allowEmpty.includes(key)) {\r\n acc[key] = value;\r\n return acc;\r\n }\r\n if (value === undefined) {\r\n return acc;\r\n }\r\n if (isPlainObject(value)) {\r\n const cleanedValue = cleanObjectFromEmptyData2(value, allowEmpty, deleteEmptyValues);\r\n if (isEmpty(cleanedValue)) {\r\n return acc;\r\n }\r\n acc[key] = cleanedValue;\r\n return acc;\r\n }\r\n if (Array.isArray(value)) {\r\n acc[key] = value.map((array) =\u003E cleanObjectFromEmptyData2(array, allowEmpty, deleteEmptyValues));\r\n return acc;\r\n }\r\n if (deleteEmptyValues \u0026\u0026 isEmpty(value)) {\r\n return acc;\r\n }\r\n acc[key] = value;\r\n return acc;\r\n }, {});\r\n};\r\n\r\nclass Cleaner {\r\n constructor(options) {\r\n this.options = options\r\n }\r\n\r\n clean(data) {\r\n if(!data) return data;\r\n \r\n if(Array.isArray(data)) return this._cleanArray(data);\r\n\r\n if(this._isObject(data)) return this.options.cleanInPlace? this._cleanObjectInPlace(data) : this._cleanObject(data);\r\n\r\n return data;\r\n }\r\n\r\n _cleanArray(arr) {\r\n return this.options.cleanInPlace ? this._getFilteredArrayInPlace(arr) : this._getFilteredArray(arr)\r\n }\r\n\r\n _cleanObjectInPlace(object) {\r\n Object.keys(object).forEach((key) =\u003E {\r\n const value = object[key];\r\n\r\n if (Array.isArray(value)) {\r\n const mappedArr = this._cleanArray(value);\r\n if(this._shouldReturnArray(mappedArr)) object[key] = mappedArr;\r\n else delete object[key];\r\n } else if (this._isObject(value)) {\r\n const subFiltered = this.clean(value);\r\n if(this._shouldReturnObject(subFiltered)) object[key] = subFiltered;\r\n else delete object[key];\r\n } else {\r\n if (this._shouldRemoveValue(value)) delete object[key]\r\n }\r\n })\r\n\r\n return object\r\n }\r\n\r\n _cleanObject(object) {\r\n const filtered = {};\r\n \r\n Object.keys(object).forEach(key =\u003E {\r\n const value = object[key];\r\n\r\n if (Array.isArray(value)) {\r\n const mappedArr = this._cleanArray(value);\r\n if (this._shouldReturnArray(mappedArr)) filtered[key] = mappedArr;\r\n } else if (this._isObject(value)) {\r\n const subFiltered = this.clean(value);\r\n if (this._shouldReturnObject(subFiltered)) filtered[key] = subFiltered;\r\n } else {\r\n if (!this._shouldRemoveValue(value)) filtered[key] = value;\r\n }\r\n });\r\n \r\n return filtered;\r\n }\r\n\r\n _getFilteredArrayInPlace (arr) {\r\n for (let i = arr.length - 1; i \u003E= 0; i--) {\r\n const item = arr[i];\r\n const filteredItem = this.clean(item);\r\n\r\n if(this._isObject(filteredItem)) {\r\n if(this._shouldReturnObject(filteredItem)) arr[i] = filteredItem\r\n else arr.splice(i , 1);\r\n }\r\n else if(Array.isArray(filteredItem)) {\r\n if (this._shouldReturnArray(filteredItem)) arr[i] = filteredItem\r\n else arr.splice(i, 1);\r\n }\r\n else if(this._shouldRemoveValue(filteredItem)) arr.splice(i, 1);\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n _getFilteredArray (arr) {\r\n const filteredArr = [];\r\n arr.forEach(item =\u003E {\r\n const filteredItem = this.clean(item);\r\n if(this._isObject(filteredItem)) {\r\n if(this._shouldReturnObject(filteredItem)) filteredArr.push(filteredItem);\r\n }\r\n else if(Array.isArray(filteredItem)) {\r\n if (this._shouldReturnArray(filteredItem)) filteredArr.push(filteredItem);\r\n }\r\n else if(!this._shouldRemoveValue(filteredItem)) filteredArr.push(filteredItem);\r\n });\r\n \r\n return filteredArr;\r\n }\r\n\r\n _isObject (value) {\r\n return Object.prototype.toString.call(value) === \u0022[object Object]\u0022\r\n }\r\n\r\n _shouldReturnArray (arr) {\r\n return !this.options.emptyArraysCleaner || arr.length !== 0\r\n }\r\n\r\n _shouldReturnObject (object) {\r\n return !this.options.emptyObjectsCleaner || Object.keys(object).length !== 0\r\n }\r\n\r\n _shouldRemoveValue (value) {\r\n if(value === null) return this.options.nullCleaner\r\n \r\n if(value === \u0022\u0022) return this.options.emptyStringsCleaner\r\n \r\n if(Number.isNaN(value)) return this.options.nanCleaner\r\n\r\n if(value === undefined) return true\r\n \r\n return false\r\n }\r\n}\r\n\r\nconst getDefaultOptions = (options) =\u003E {\r\n const optionsToRead = options || {}\r\n\r\n const defaultedOptions = {\r\n nullCleaner: optionsToRead.hasOwnProperty(\u0027nullCleaner\u0027) ? optionsToRead.nullCleaner : true,\r\n emptyArraysCleaner: optionsToRead.hasOwnProperty(\u0027emptyArraysCleaner\u0027) ? optionsToRead.emptyArraysCleaner : true,\r\n emptyObjectsCleaner: optionsToRead.hasOwnProperty(\u0027emptyObjectsCleaner\u0027) ? optionsToRead.emptyObjectsCleaner : true,\r\n emptyStringsCleaner: optionsToRead.hasOwnProperty(\u0027emptyStringsCleaner\u0027) ? optionsToRead.emptyStringsCleaner : true,\r\n nanCleaner: optionsToRead.hasOwnProperty(\u0027nanCleaner\u0027) ? optionsToRead.nanCleaner : true,\r\n cleanInPlace: optionsToRead.hasOwnProperty(\u0027cleanInPlace\u0027) ? optionsToRead.cleanInPlace : true,\r\n }\r\n\r\n return defaultedOptions\r\n}\r\n\r\nvar clean = (object, options) =\u003E {\r\n const defaultedOptions = getDefaultOptions(options)\r\n const cleaner = new Cleaner(defaultedOptions);\r\n return cleaner.clean(object);\r\n };\r\n\r\n\r\n var obj = {\r\n a: {\r\n b: {\r\n c: \u0027\u0027,\r\n d: {\r\n e: null,\r\n f: \u0027value\u0027,\r\n g: {\r\n h: \u0027\u0027,\r\n i: \u0027value2\u0027,\r\n },\r\n j: undefined,\r\n k: 0,\r\n },\r\n },\r\n },\r\n j: undefined,\r\n };\r\n","TestCases":[{"Name":"cleanObjectFromEmptyData1","Code":"cleanObjectFromEmptyData1(obj, undefined, true);","IsDeferred":false},{"Name":"cleanObjectFromEmptyData2","Code":"cleanObjectFromEmptyData2(obj, undefined, true);","IsDeferred":false},{"Name":"clean","Code":"clean(obj, undefined, true);","IsDeferred":false}]}