flattenObjectKeys() function in Refine source code.

Ramu NarasingaRamu Narasinga
2 min read

In this article, we will review a function, flattenObjectKeys, in Refine source code.

const isNested = (obj: any) => typeof obj === "object" && obj !== null;
const isArray = (obj: any) => Array.isArray(obj);

export const flattenObjectKeys = (obj: any, prefix = "") => {
  if (!isNested(obj)) {
    return {
      [prefix]: obj,
    };
  }

  return Object.keys(obj).reduce(
    (acc, key) => {
      const currentPrefix = prefix.length ? `${prefix}.` : "";

      if (isNested(obj[key]) && Object.keys(obj[key]).length) {
        if (isArray(obj[key]) && obj[key].length) {
          obj[key].forEach((item: unknown[], index: number) => {
            Object.assign(
              acc,
              flattenObjectKeys(item, `${currentPrefix + key}.${index}`),
            );
          });
        } else {
          Object.assign(acc, flattenObjectKeys(obj[key], currentPrefix + key));
        }
        // Even if it's a nested object, it should be treated as a key as well
        acc[currentPrefix + key] = obj[key];
      } else {
        acc[currentPrefix + key] = obj[key];
      }
      return acc;
    },
    {} as Record<string, unknown>,
  );
};

This code snippet is picked from the file shown in the below image:

This is recursive function that calls it self to create an object with flattened keys. I was going to copy this over and provide a sample object but I found that such an example already exists in the test case.

it("should flatten an object with nested objects and arrays", () => {
    const obj = {
      a: 1,
      b: {
        c: 2,
        d: [3, 4],
      },
      e: {
        f: {
          g: 5,
        },
      },
    };

    const flattenedObj = flattenObjectKeys(obj);

    expect(flattenedObj).toEqual({
      a: 1,
      b: {
        c: 2,
        d: [3, 4],
      },
      "b.c": 2,
      "b.d": [3, 4],
      "b.d.0": 3,
      "b.d.1": 4,
      e: {
        f: {
          g: 5,
        },
      },
      "e.f": {
        g: 5,
      },
      "e.f.g": 5,
    });
  });

You get the idea, right? the object below:

{
    a: 1,
    b: {
      c: 2,
      d: [3, 4],
    },
    e: {
      f: {
        g: 5,
      },
    },
};

gets flattened to something like below:

{
  a: 1,
  b: {
    c: 2,
    d: [3, 4],
  },
  "b.c": 2,
  "b.d": [3, 4],
  "b.d.0": 3,
  "b.d.1": 4,
  e: {
    f: {
      g: 5,
    },
  },
  "e.f": {
    g: 5,
  },
  "e.f.g": 5,
}

For more test cases, check out this file — flatten-object-keys/index.spec.ts

About me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

I am open to work on interesting projects. Send me an email at ramu.narasinga@gmail.com

My Github —  https://github.com/ramu-narasinga

My website —  https://ramunarasinga.com

My Youtube channel —  https://www.youtube.com/@ramu-narasinga

Learning platform —  https://thinkthroo.com

Codebase Architecture —  https://app.thinkthroo.com/architecture

Best practices —  https://app.thinkthroo.com/best-practices

Production-grade projects —  https://app.thinkthroo.com/production-grade-projects

References:

  1. https://github.com/refinedev/refine/blob/main/packages/core/src/definitions/helpers/flatten-object-keys/index.ts
0
Subscribe to my newsletter

Read articles from Ramu Narasinga directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ramu Narasinga
Ramu Narasinga

I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.