javascriptunderscore.js

One liner to flatten nested object


I need to flatten a nested object. Need a one liner. Not sure what the correct term for this process is. I can use pure Javascript or libraries, I particularly like underscore.

I've got ...

{
  a:2,
  b: {
    c:3
  }
}

And I want ...

{
  a:2,
  c:3
}

I've tried ...

var obj = {"fred":2,"jill":4,"obby":{"john":5}};
var resultObj = _.pick(obj, "fred")
alert(JSON.stringify(resultObj));

Which works but I also need this to work ...

var obj = {"fred":2,"jill":4,"obby":{"john":5}};
var resultObj = _.pick(obj, "john")
alert(JSON.stringify(resultObj));

Solution

  • 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)
    )