Skip to the code
cf.

Flatten an object

Write flattenObject(object). It returns a new, one-level object whose keys are the dotted paths to the values in object.

flattenObject({ user: { name: "Ada", tags: ["math", "code"] }, active: true });
// { "user.name": "Ada", "user.tags.0": "math", "user.tags.1": "code", active: true }

Walk into plain objects and arrays: object keys and array indexes become parts of the path. Anything else is a value and is kept as it is, by reference: null, undefined, dates, class instances, and functions. An empty object or array is kept as a value too, so no key disappears.

What the tests check

  1. joins nested keys with dots
    expect(flattenObject({ a: { b: 1, c: { d: 2 } }, e: 3 })).toEqual({ "a.b": 1, "a.c.d": 2, e: 3 });
    
  2. uses indexes for array items
    expect(flattenObject({ a: [1, { b: 2 }] })).toEqual({ "a.0": 1, "a.1.b": 2 });
    
  3. keeps null and undefined values
    expect(flattenObject({ a: null, b: { c: undefined } })).toEqual({ a: null, "b.c": undefined });
    
  4. keeps empty objects and arrays as values
    expect(flattenObject({ a: {}, b: [], c: { d: {} } })).toEqual({ a: {}, b: [], "c.d": {} });
    
  5. keeps dates, class instances, and functions as they are
    class Point {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
    }
    const when = new Date(0);
    const at = new Point(1, 2);
    const fn = () => {};
    const flat = flattenObject({ meta: { when, at, fn } });
    expect(Object.keys(flat).sort()).toEqual(["meta.at", "meta.fn", "meta.when"]);
    expect(flat["meta.when"]).toBe(when);
    expect(flat["meta.at"]).toBe(at);
    expect(flat["meta.fn"]).toBe(fn);
    
  6. returns a new object and leaves the input alone
    const input = { a: { b: 1 } };
    const flat = flattenObject(input);
    expect(flat).not.toBe(input);
    expect(input).toEqual({ a: { b: 1 } });
    expect(flattenObject({})).toEqual({});
    

Learn more

solution.jsSaved in this browser

Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.

Ctrl + Enter runs the tests (⌘ + Enter on a Mac).