flattenObject
Recursively flattens a nested object using dot notation for keys.
1/**
2 * Recursively flattens a nested object using dot notation for keys.
3 *
4 * @param obj - The object to flatten.
5 * @param prefix - Internal use only: prefix for nested keys.
6 * @returns A new flat object with dot-separated keys.
7 */
8export function flattenObject(obj: any, prefix = ''): Record<string, any> {
9 return Object.keys(obj).reduce((acc, key) => {
10 const fullKey = prefix ? `${prefix}.${key}` : key;
11 const value = obj[key];
12
13 if (value && typeof value === 'object' && !Array.isArray(value)) {
14 Object.assign(acc, flattenObject(value, fullKey));
15 } else {
16 acc[fullKey] = value;
17 }
18
19 return acc;
20 }, {} as Record<string, any>);
21}
Recursive Deep Flattening
Converts arbitrarily nested objects into a flat structure using dot notation, making deeply nested data easier to work with.
Preserves Key Hierarchy
Encodes the original structure into dot-separated keys, allowing for accurate reconstruction or reference.
Handles Arbitrary Nesting Levels
Works on deeply nested objects without hardcoded depth limits or special cases.
Clean and Extensible
Minimal and readable logic that can be extended to support arrays, custom delimiters, or filters if needed.
Tests | Examples
1test('flattenObject - flattens a simple nested object', () => {
2 const input = { a: { b: 1 } };
3 const expected = { 'a.b': 1 };
4 expect(flattenObject(input)).toEqual(expected);
5});
6
7test('flattenObject - handles multiple levels of nesting', () => {
8 const input = { a: { b: { c: { d: 2 } } } };
9 const expected = { 'a.b.c.d': 2 };
10 expect(flattenObject(input)).toEqual(expected);
11});
12
13test('flattenObject - ignores arrays (treats them as values)', () => {
14 const input = { a: [1, 2], b: { c: 3 } };
15 const expected = { 'a': [1, 2], 'b.c': 3 };
16 expect(flattenObject(input)).toEqual(expected);
17});
18
19test('flattenObject - preserves primitive values', () => {
20 const input = { a: 1, b: 'text', c: false };
21 const expected = { a: 1, b: 'text', c: false };
22 expect(flattenObject(input)).toEqual(expected);
23});
24
25test('flattenObject - handles empty object', () => {
26 expect(flattenObject({})).toEqual({});
27});
28
29test('flattenObject - handles null and undefined properly', () => {
30 const input = { a: null, b: undefined, c: { d: null } };
31 const expected = { a: null, b: undefined, 'c.d': null };
32 expect(flattenObject(input)).toEqual(expected);
33});
Common Use Cases
Form Handling and Validation
Flatten nested form state to easily bind inputs, validate fields, or send structured payloads.
API Interactions
Convert complex payloads into flat structures for compatibility with systems that don't support nested keys.
Configuration Management
Flatten deeply nested config files or environment overrides for simpler parsing or injection.
Logging and Debugging
Log complex objects in a flattened format for better visibility in structured logs.
Data Normalization
Preprocess JSON or database records for storage in flat-schema systems like spreadsheets or key-value stores.