|
|
|
@ -1,19 +1,29 @@ |
|
|
|
|
import { isArray, isPlainObject } from 'lodash'; |
|
|
|
|
|
|
|
|
|
/** @returns a deep clone of the object, but with any null value removed */ |
|
|
|
|
export function sortedDeepCloneWithoutNulls<T>(value: T): T { |
|
|
|
|
/** |
|
|
|
|
* @returns A deep clone of the object, but with any null value removed. |
|
|
|
|
* @param value - The object to be cloned and cleaned. |
|
|
|
|
* @param convertInfinity - If true, -Infinity or Infinity is converted to 0. |
|
|
|
|
* This is because Infinity is not a valid JSON value, and sometimes we want to convert it to 0 instead of default null. |
|
|
|
|
*/ |
|
|
|
|
export function sortedDeepCloneWithoutNulls<T>(value: T, convertInfinity?: boolean): T { |
|
|
|
|
if (isArray(value)) { |
|
|
|
|
return value.map(sortedDeepCloneWithoutNulls) as unknown as T; |
|
|
|
|
return value.map((item) => sortedDeepCloneWithoutNulls(item, convertInfinity)) as unknown as T; |
|
|
|
|
} |
|
|
|
|
if (isPlainObject(value)) { |
|
|
|
|
return Object.keys(value as { [key: string]: any }) |
|
|
|
|
.sort() |
|
|
|
|
.reduce((acc: any, key) => { |
|
|
|
|
const v = (value as any)[key]; |
|
|
|
|
// Remove null values and also -Infinity which is not a valid JSON value
|
|
|
|
|
if (v != null && v !== -Infinity) { |
|
|
|
|
acc[key] = sortedDeepCloneWithoutNulls(v); |
|
|
|
|
// Remove null values
|
|
|
|
|
if (v != null) { |
|
|
|
|
acc[key] = sortedDeepCloneWithoutNulls(v, convertInfinity); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (convertInfinity && (v === Infinity || v === -Infinity)) { |
|
|
|
|
acc[key] = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return acc; |
|
|
|
|
}, {}); |
|
|
|
|
} |
|
|
|
|