Skip to content

Instantly share code, notes, and snippets.

@dmitru
Last active April 23, 2018 17:08
Show Gist options
  • Save dmitru/f4168cd32899281b068d953e7f76fe4a to your computer and use it in GitHub Desktop.
Save dmitru/f4168cd32899281b068d953e7f76fe4a to your computer and use it in GitHub Desktop.
Function for deep object flattening (see test cases)
import map from 'lodash/map'
function deepFlattenHelper(obj, acc = {}, path = []) {
if (!obj) {
return acc
}
let result = { ...acc }
if (typeof obj === 'object') {
map(obj, (value, key) => {
if (typeof value === 'object') {
result = {
...result,
...deepFlattenHelper(value, acc, path.concat(key)),
}
} else if (typeof value !== 'undefined') {
result[path.concat(key).join('.')] = value
}
})
}
return result
}
export default function deepFlatten(obj) {
if (!obj) {
return obj
}
return deepFlattenHelper(obj)
}
import deepFlatten from './deepFlatten'
describe('utils/deepFlatten', () => {
it('Should work for an empty object', async () => {
const result = deepFlatten({})
expect(result).toEqual({})
})
it('Should work for a null', async () => {
const result = deepFlatten(null)
expect(result).toEqual(null)
})
it('Should work for an undefined', async () => {
const result = deepFlatten(undefined)
expect(result).toEqual(undefined)
})
it('Should work for a 1-level object', async () => {
const result = deepFlatten({ a: 1, b: 2 })
expect(result).toEqual({ a: 1, b: 2 })
})
it('Should work for a 1-level object with array', async () => {
const result = deepFlatten({ a: 1, b: 2, c: [3] })
expect(result).toEqual({ a: 1, b: 2, 'c.0': 3 })
})
it('Should deeply filter all undefined values', async () => {
const result = deepFlatten([
{ a: undefined, b: { bb: undefined }, c: [undefined, { d: undefined, e: { f: undefined } }] },
])
expect(result).toEqual({})
})
it('Should work for arrays with missing indices', async () => {
const array = []
array[1] = 'a'
array[2] = 'b'
const result = deepFlatten({ a: array })
expect(result).toEqual({ 'a.1': 'a', 'a.2': 'b' })
expect(Object.keys(result)).toEqual(['a.1', 'a.2'])
})
it('Should work for a 2-level object with an array', async () => {
const result = deepFlatten({ a: { b: 2, c: [3, 4, { d: 5 }] } })
expect(result).toEqual({ 'a.b': 2, 'a.c.0': 3, 'a.c.1': 4, 'a.c.2.d': 5 })
})
it('Should work for a deep complex mixed object with arrays', async () => {
const result = deepFlatten({ a: { b: 2, c: [3, 4, { d: 5, e: [{ f: 6 }] }] } })
expect(result).toEqual({ 'a.b': 2, 'a.c.0': 3, 'a.c.1': 4, 'a.c.2.d': 5, 'a.c.2.e.0.f': 6 })
})
it('Should work for an array of objects', async () => {
const result = deepFlatten([1, { b: 2 }])
expect(result).toEqual({ '0': 1, '1.b': 2 })
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment