I'm trying to flatten a data object that contains mixed content (JavaScript within a React application). I just need the keys of every parent and child in the object; I don't necessarily need the values (though having them present wouldn't be a deal-breaker).
I've searched for over a week to find a solution that would fit my use case, but everything I've tried has fallen short, including vanilla JavaScript, Lodash, Underscore, and flat (NPM package).
In every case, I either get a shorter list than I expect (because I'm only getting the parents), or I get a fully-flattened object with dot notation-delimited objects, which is useless to me.
I know there are lots of questions & answers pertaining to this topic, but nothing I've seen matches my use case, and I can't seem to wrap my head around the problem.
Here is a sample of my data structure:
const sampleData = {
coyotes: '',
armadillos: false,
wombats: [''],
geckos: 0,
dogs: {
beagle: '',
bulldog: ''
},
wolves: [
{
type: '',
color: '',
range: '',
status: {
endangered: true,
protected: false
}
}
],
cats: {}
}
Here is what I (ideally) want back:
result = {coyotes, armadillos, wombats, geckos, dogs, beagle, bulldog, wolves, type, color, range, status, endangered, protected, cats}
Here is the way I'd like to call the flattening method:
flattenData(sampleData)
Here's what I have so far:
const flattenData = (obj) =>
Object.assign(
{},
...(function _flatten (o) {
return [].concat(...Object.keys(o)
.map(k =>
typeof o[k] === 'object' ? _flatten(o[k]) : (Number([k]) !== 0 && { [k]: o[k] })
)
)
}(obj))
)
...which produces:
{
"coyotes": "",
"armadillos": false,
"geckos": 0,
"beagle": "",
"bulldog": "",
"type": "",
"color": "",
"range": "",
"endangered": true,
"protected": false
}
As you'll note, some parents are missing (wombats, dogs, wolves and status), and an empty object is missing (cats).
Here's a simple recursion:
const deepKeys = (o) =>
Array .isArray (o)
? o .flatMap (deepKeys)
: Object (o) === o
? Object .entries (o) .flatMap (([k, v]) => [k, ... deepKeys (v)])
: []
const sampleData = {coyotes: '', armadillos: false, wombats: [''], geckos: 0, dogs: {beagle: '', bulldog: ''}, wolves: [{type: '', color: '', range: '', status: {endangered: true, protected: false}}], cats: {}}
console .log (deepKeys (sampleData))
.as-console-wrapper {max-height: 100% !important; top: 0}
We need to process a little differently for arrays, objects, and other types, but each one is fairly simple.