lodash 的 flatten、flattenDeep 或 flattenDepth 只接受数组。如何展平嵌套对象?
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
}
}
我希望嵌套属性是第一级,比如 expiry_date 应该是第一级,而不是在日期内,而且我认为日期应该消失,不再需要了。我可以手动完成,使用 map() 但我希望使用 lodash 来简化任务。
最简单的解决方案之一是将嵌套对象与父对象合并,
_.merge(data, data.dates);
这会将所有
data.dates
财产带入 data
。然后删除data.dates
delete data.dates
ES6版本:
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)
需要注意的一件事是,必须小心深层嵌套的解构。在此示例中,如果
data.dates
是 undefined
并且您尝试对其进行解构,则会抛出错误。
您可以 .merge() .get() 和 _.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>
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;
}
如果您正在寻找现有的解决方案,您可以使用名为 flat 的库,如此 lodash github 问题
中所述这可以使用任何深度的嵌套对象和数组来展平对象。结果对象中的键是输入对象中属性的完整路径
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;
}
如果您需要展平整个对象,而不仅仅是其“日期”属性,类似这样的东西应该可以工作,您甚至不需要lodash:
var data = {
"dates": {
"expiry_date": "30 sep 2018",
"available": "30 sep 2017",
"min_contract_period": [/*...*/]
},
"price": {
"curreny": "RM",
"min": 1500,
"max": 2000
}
};
const flattenedObj = flattenObject(data);
// {
// "expiry_date": "30 sep 2018",
// "available": "30 sep 2017",
// "min_contract_period": [/*...*/],
// "curreny": "RM",
// "min": 1500,
// "max": 2000
// }
function flattenObject(obj) {
const result = {};
Object.entries(obj).forEach(([key, val]) => {
// if object (and not null!), merge it with the resulting object,
// otherwise just copy the value
if (val && typeof val === "object")
Object.assign(result, val);
else
result[key] = val;
});
return result;
}