All files flattenObject.ts

100% Statements 25/25
91.18% Branches 31/34
100% Functions 4/4
100% Lines 25/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69    1x           1x           10x 10x   9x     9x           2x 2x     7x   7x 15x 15x   8x   7x       7x     1x     1x 1x 1x 9x 9x 9x 9x 23x                     1x    
// stackoverflow.com/questions/44134212/best-way-to-flatten-js-object-keys-and-values-to-a-single-depth-array
 
export function flattenObject(
  obj: Record<string, unknown>,
  options?: {
    separator?: string;
  }
) {
  const defaultOptions = {
    separator: '.',
    ...(options || {}),
  };
  function flt(
    obj: any,
    prefix = '',
    result: null | Record<string, unknown> = null
  ) {
    result = result || {};
 
    // Preserve empty objects and arrays, they are lost otherwise
    if (
      prefix &&
      typeof obj === 'object' &&
      obj !== null &&
      Object.keys(obj).length === 0
    ) {
      result[prefix] = Array.isArray(obj) ? [] : {};
      return result;
    }
 
    prefix = prefix ? prefix + `${defaultOptions.separator}` : '';
 
    for (const i in obj) {
      Eif (Object.prototype.hasOwnProperty.call(obj, i)) {
        if (typeof obj[i] === 'object' && obj[i] !== null) {
          // Recursion on deeper objects
          flt(obj[i], prefix + i, result);
        } else {
          result[prefix + i] = obj[i];
        }
      }
    }
    return result;
  }
 
  return flt(obj);
}
 
export function unFlattenObject(obj: Record<string, unknown>) {
  const result = {};
  for (const i in obj) {
    Eif (Object.prototype.hasOwnProperty.call(obj, i)) {
      const keys = i.match(/^\.+[^.]*|[^.]*\.+$|(?:\.{2,}|[^.])+(?:\.+$)?/g); // Just a complicated regex to only match a single dot in the middle of the string
      Iif (keys == null) return result;
      keys.reduce((r: any, e, j) => {
        return (
          r[e] ||
          (r[e] = isNaN(Number(keys[j + 1]))
            ? keys.length - 1 === j
              ? obj[i]
              : {}
            : [])
        );
      }, result);
    }
  }
  return result;
}