如何使用Ramda实现类似Lodash.set的功能,为JSON对象新增嵌套条目
Ramda实现嵌套属性赋值方案
Ramda 中对应 Lodash _.set 功能的方法是 R.assocPath,该方法为纯函数,不会修改原对象,会返回更新后的新对象,适配需求的实现方式如下:
1. 逐行对应实现(和原有写法逻辑完全对齐)
const R = require('ramda'); const incomingData = { firstName: 'Pete', lastName: 'Cathy', middleInitial: 'M', maidenName: 'catty' }; // 初始空对象 let data = {}; // 逐个设置属性,R.assocPath返回新对象,所以重新赋值给data data = R.assocPath(['client', 'firstName'], incomingData.firstName ?? '', data); data = R.assocPath(['client', 'lastName'], incomingData.lastName ?? '', data); data = R.assocPath(['client', 'middleInitial'], incomingData.middleInitial ?? '', data); data = R.assocPath(['maidenName'], incomingData.maidenName ?? '', data);
说明:这里用
??空值合并运算符仅会将undefined/null替换为空字符串,如果需要和原有三元判断逻辑完全一致(所有falsy值都返回空字符串),可以替换为||运算符。
2. 批量映射实现(字段较多时更简洁,无冗余代码)
如果需要设置的字段很多,可以把路径和取值规则做成映射表,用R.pipe组合所有赋值操作:
const R = require('ramda'); const incomingData = { firstName: 'Pete', lastName: 'Cathy', middleInitial: 'M', maidenName: 'catty' }; // 定义属性配置:[路径数组, 取值函数] const propConfigs = [ [['client', 'firstName'], () => incomingData.firstName || ''], [['client', 'lastName'], () => incomingData.lastName || ''], [['client', 'middleInitial'], () => incomingData.middleInitial || ''], [['maidenName'], () => incomingData.maidenName || ''], // 后续新增字段直接加配置即可 ]; // 批量组合赋值操作,生成最终对象 const data = R.pipe( ...propConfigs.map(([path, getVal]) => R.assocPath(path, getVal())) )({});
输出结果
两种写法最终得到的data结构完全符合预期:
{ "client": { "firstName": "Pete", "lastName": "Cathy", "middleInitial": "M" }, "maidenName": "catty" }
可选:封装点分隔路径兼容方法
如果习惯用Lodash风格的点分隔字符串路径,可以自行封装简易的适配方法:
const setByPath = R.curry((pathStr, value, target) => R.assocPath(R.split('.', pathStr), value, target) ); // 使用方式和Lodash几乎一致,区别是不会修改原对象,返回新对象 data = setByPath('client.firstName', incomingData.firstName || '', data);
内容的提问来源于stack exchange,提问作者Codewrapper
相关产品推荐
相关产品推荐

