One liner to flatten nested object
Simplified readable example, no dependencies
/**
* Flatten a multidimensional object
*
* For example:
* flattenObject{ a: 1, b: { c: 2 } }
* Returns:
* { a: 1, c: 2}
*/
export const flattenObject = (obj) => {
const flattened = {}
Object.keys(obj).forEach((key) => {
const value = obj[key]
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
Object.assign(flattened, flattenObject(value))
} else {
flattened[key] = value
}
})
return flattened
}
Features
- No dependencies
- Works with null values
- Works with arrays
- Working example https://jsfiddle.net/webbertakken/jn613d8p/26/
Here is a true, crazy one-liner that flats the nested object recursively:
const flatten = (obj, roots=[], sep='.') => Object.keys(obj).reduce((memo, prop) => Object.assign({}, memo, Object.prototype.toString.call(obj[prop]) === '[object Object]' ? flatten(obj[prop], roots.concat([prop]), sep) : {[roots.concat([prop]).join(sep)]: obj[prop]}), {})
Multiline version, explained:
// $roots keeps previous parent properties as they will be added as a prefix for each prop.
// $sep is just a preference if you want to seperate nested paths other than dot.
const flatten = (obj, roots = [], sep = '.') => Object
// find props of given object
.keys(obj)
// return an object by iterating props
.reduce((memo, prop) => Object.assign(
// create a new object
{},
// include previously returned object
memo,
Object.prototype.toString.call(obj[prop]) === '[object Object]'
// keep working if value is an object
? flatten(obj[prop], roots.concat([prop]), sep)
// include current prop and value and prefix prop with the roots
: {[roots.concat([prop]).join(sep)]: obj[prop]}
), {})
An example:
const obj = {a: 1, b: 'b', d: {dd: 'Y'}, e: {f: {g: 'g'}}}
const flat = flatten(obj)
{
'a': 1,
'b': 'b',
'd.dd': 'Y',
'e.f.g': 'g'
}
Happy one-liner day!
Here you go:
Object.assign({}, ...function _flatten(o) { return [].concat(...Object.keys(o).map(k => typeof o[k] === 'object' ? _flatten(o[k]) : ({[k]: o[k]})))}(yourObject))
Summary: recursively create an array of one-property objects, then combine them all with Object.assign
.
This uses ES6 features including Object.assign
or the spread operator, but it should be easy enough to rewrite not to require them.
For those who don't care about the one-line craziness and would prefer to be able to actually read it (depending on your definition of readability):
Object.assign(
{},
...function _flatten(o) {
return [].concat(...Object.keys(o)
.map(k =>
typeof o[k] === 'object' ?
_flatten(o[k]) :
({[k]: o[k]})
)
);
}(yourObject)
)