'flatten nested object using lodash
flatten, flattenDeep or flattenDepth of lodash only accept array. How to flatten nested object?
var data = {
"dates": {
"expiry_date": "30 sep 2018",
"available": "30 sep 2017",
"min_contract_period": [{
"id": 1,
"name": "1 month",
"value": false
}, {
"id": 2,
"name": "2 months",
"value": true
}, {
"id": 3,
"name": "3 months",
"value": false
}]
},
"price": {
"curreny": "RM",
"min": 1500,
"max": 2000
}
}
I want nested property to be the first level, like expiry_date should be level 1, not within dates, and I think dates should be gone, it's not needed anymore. I can do it manually, use map() but I'm looking to use lodash to ease the task.
Solution 1:[1]
One of the easiest solutions would be, merging the nested object with parent,
_.merge(data, data.dates);
This will bring all data.dates
property into data
. Then delete data.dates
delete data.dates
Solution 2:[2]
ES6 version:
var data = {
"dates": {
"expiry_date": "30 sep 2018",
"available": "30 sep 2017",
"min_contract_period": [{
"id": 1,
"name": "1 month",
"value": false
}, {
"id": 2,
"name": "2 months",
"value": true
}, {
"id": 3,
"name": "3 months",
"value": false
}]
},
"price": {
"curreny": "RM",
"min": 1500,
"max": 2000
}
};
var {dates: {expiry_date, ...dates}, ...rest} = data;
var flatData = {dates, expiry_date, ...rest}
console.log(flatData)
One thing to note is that you have to be careful with deeply nested destructuting. In this example if data.dates
is undefined
and you'll try to destructure it, error will be thrown.
Solution 3:[3]
You can .merge() the result of .get() and _.pick():
var data = {"dates": {"expiry_date": "30 sep 2018","available": "30 sep 2017","min_contract_period": [{"id": 1,"name": "1 month","value": false}, {"id": 2,"name": "2 months","value": true}, {"id": 3,"name": "3 months","value": false}]},"price": {"curreny": "RM","min": 1500,"max": 2000}},
result = _.merge(_.get(data, 'dates'), _.pick(data, 'price'));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Solution 4:[4]
function flattenObject(o, prefix = '', result = {}, keepNull = true) {
if (_.isString(o) || _.isNumber(o) || _.isBoolean(o) || (keepNull && _.isNull(o))) {
result[prefix] = o;
return result;
}
if (_.isArray(o) || _.isPlainObject(o)) {
for (let i in o) {
let pref = prefix;
if (_.isArray(o)) {
pref = pref + `[${i}]`;
} else {
if (_.isEmpty(prefix)) {
pref = i;
} else {
pref = prefix + '.' + i;
}
}
flattenObject(o[i], pref, result, keepNull);
}
return result;
}
return result;
}
Solution 5:[5]
this flattens object with nested objects and arrays of any depth. keys in resulting object are full paths to properties in input object
public static flattenObject(o: any, prefix?: string, result?: any): any {
prefix = prefix ? prefix : '';
result = result ? result : {};
if (_.isString(o) || _.isNumber(o) || _.isBoolean(o)) {
result[prefix] = o;
return result;
}
if (_.isArray(o) || _.isPlainObject(o)) {
for (let i in o) {
let pref = prefix;
if (_.isArray(o)) {
pref = pref + `[${i}]`;
} else {
if (_.isEmpty(prefix)) {
pref = i;
} else {
pref = prefix + '.' + i;
}
}
Utils.flattenObject(o[i], pref, result);
}
return result;
}
return result;
}
Solution 6:[6]
If you need to flatten the whole object, not only its "dates" property, something like this should work, you don't even need lodash:
function flattenObject(obj) {
const result = {};
Object.values(obj).forEach(nestedObject => {
Object.assign(result, nestedObject);
});
return result;
}
Solution 7:[7]
If you're looking for an existing solution you can use a library called flat, as it said in this issue
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | RaR |
Solution 2 | |
Solution 3 | |
Solution 4 | |
Solution 5 | Andrey |
Solution 6 | Alexey Grinko |
Solution 7 | ilyavysotski |