需求
替换对象里面的字段,而且里面有不确定层级的数值,里面再次嵌套对象,原始数据代码如下:
const targetObj = {
companyCnt: 2317547,
industryCnt: 23,
industryCode: "105",
level: 1,
name: "5G产业",
downstream: [
{
downstream: [
{ industryCode: "1050101", level: 3, name: "网络规划/设计" },
{ industryCode: "1050102", level: 3, name: "网络工程/优化" },
],
industryCnt: 3,
industryCode: "10501",
level: 2,
name: "支撑层",
},
{
downstream: [
{ industryCode: "1050201", level: 3, name: "芯片" },
{ industryCode: "1050202", level: 3, name: "射频器件" },
{ industryCode: "1050203", level: 3, name: "关键材料" },
],
industryCnt: 4,
industryCode: "10502",
level: 2,
name: "基础层",
},
{
downstream: [
{ industryCode: "1050301", level: 3, name: "主设备" },
{ industryCode: "1050302", level: 3, name: "基站天线" },
{ industryCode: "1050303", level: 3, name: "SDN/NFV解决方案" },
{ industryCode: "1050304", level: 3, name: "光纤光缆" },
{ industryCode: "1050305", level: 3, name: "射频滤波器" },
{ industryCode: "1050306", level: 3, name: "光模块/光器件" },
{ industryCode: "1050307", level: 3, name: "小基站" },
{ industryCode: "1050308", level: 3, name: "基站配套" },
],
industryCnt: 9,
industryCode: "10503",
level: 2,
name: "传输层",
},
{
downstream: [
{ industryCode: "1050401", level: 3, name: "系统集成" },
{ industryCode: "1050402", level: 3, name: "网络优化/维护" },
{ industryCode: "1050403", level: 3, name: "运营商" },
{ industryCode: "1050404", level: 3, name: "移动终端设备" },
{ industryCode: "1050405", level: 3, name: "其他应用层" },
],
industryCnt: 6,
industryCode: "10504",
level: 2,
name: "应用层",
},
],
};
需要把对象以及内部不确定层级的key进行替换,替换规则是industryCode 换成 id , downstream 换成children , name 换成 label,也就是说不管,层级嵌套多少都要把对象内相应的字段进行替换。实现的输出代码如下:
{
companyCnt: 2317547,
industryCnt: 23,
id: "105",// industryCode ==> id
level: 1,
label: "5G产业",// name ==> label
children: [ // downstream ==> children
{
children: [
{ id: "1050101", level: 3, label: "网络规划/设计" },
{ id: "1050102", level: 3, label: "网络工程/优化" },
...
...
],
industryCnt: 3,
id: "10501",
level: 2,
label: "支撑层",
},
.....
.....
]
}
解决办法
进行遍历和递归方式进行替换,初步实现代码如下:
// 自执行函数,进行遍历递归
(function changeKey(_obj){
for(let key in _obj){
if(key === 'industryCode'){
_obj['id'] = _obj[key]
Reflect.deleteProperty(_obj,'industryCode')
}
if(key === 'name'){
_obj['label'] = _obj[key]
Reflect.deleteProperty(_obj,'name')
}
if(key === 'downstream'){
_obj['children'] = _obj[key]
Reflect.deleteProperty(_obj,'downstream')
if(_obj['children'].length > 0){
_obj['children'].map(res =>{
changeKey(res)
})
}
}
}
})(targetObj)
console.log(targetObj)
/*
输出打印结果
{
"companyCnt": 2317547,
"industryCnt": 23,
"level": 1,
"id": "105",
"label": "5G产业",
"children": [
{
"industryCnt": 3,
"level": 2,
"children": [
{
"level": 3,
"id": "1050101",
"label": "网络规划/设计"
},
{
"level": 3,
"id": "1050102",
"label": "网络工程/优化"
}
],
"id": "10501",
"label": "支撑层"
},
{
"industryCnt": 4,
"level": 2,
"children": [
{
"level": 3,
"id": "1050201",
"label": "芯片"
},
{
"level": 3,
"id": "1050202",
"label": "射频器件"
},
{
"level": 3,
"id": "1050203",
"label": "关键材料"
}
],
"id": "10502",
"label": "基础层"
},
{
"industryCnt": 9,
"level": 2,
"children": [
{
"level": 3,
"id": "1050301",
"label": "主设备"
},
{
"level": 3,
"id": "1050302",
"label": "基站天线"
},
{
"level": 3,
"id": "1050303",
"label": "SDN/NFV解决方案"
},
{
"level": 3,
"id": "1050304",
"label": "光纤光缆"
},
{
"level": 3,
"id": "1050305",
"label": "射频滤波器"
},
{
"level": 3,
"id": "1050306",
"label": "光模块/光器件"
},
{
"level": 3,
"id": "1050307",
"label": "小基站"
},
{
"level": 3,
"id": "1050308",
"label": "基站配套"
}
],
"id": "10503",
"label": "传输层"
},
{
"industryCnt": 6,
"level": 2,
"children": [
{
"level": 3,
"id": "1050401",
"label": "系统集成"
},
{
"level": 3,
"id": "1050402",
"label": "网络优化/维护"
},
{
"level": 3,
"id": "1050403",
"label": "运营商"
},
{
"level": 3,
"id": "1050404",
"label": "移动终端设备"
},
{
"level": 3,
"id": "1050405",
"label": "其他应用层"
}
],
"id": "10504",
"label": "应用层"
}
]
}
*/
改进方法
因为每次的要改变的字段要写死在函数里,不适合直接调用,所以需要再次进行封装。
// 需要替换的数据字段
const changeKey = [
{
oldKey:'industryCode',
newKey:'id',
type:'String', // 替换的值类型
},
{
oldKey:'downstream',
newKey:'children',
type:'Array', // 替换的值类型
},
{
oldKey:'name',
newKey:'label',
type:'String', // 替换的值类型
}
]
// 进行遍历递归
function changeKey(_obj,targetKeys){
targetKeys.map(targetKey =>{
for(let key in _obj){
if(key === targetKey.oldKey){
_obj[targetKey.newKey] = _obj[key]
Reflect.deleteProperty(_obj, key)
if(targetKey.type === 'Array' && _obj[targetKey.newKey].length > 0){
_obj[targetKey.newKey].map(res =>{
changeKey(res,targetKeys)
})
}
}
}
})
}
// 调用
changeKey(targetObj,targetKeys)
小小改进
不难发现,这边最终会把原来的原始数据targetObj进行变更,需要在调整下,使其生成新的对象。
// 需要替换的数据字段
const changeKey = [
{
oldKey:'industryCode',
newKey:'id',
type:'String', // 替换的值类型
},
{
oldKey:'downstream',
newKey:'children',
type:'Array', // 替换的值类型
},
{
oldKey:'name',
newKey:'label',
type:'String', // 替换的值类型
}
]
// 深拷贝&返回
function replaceField(targetObj,targetKeys){
let _obj = JSON.parse(JSON.stringify(targetObj))
changeKey(_obj,targetKeys)
return _obj
}
// 进行遍历递归
function changeKey(_obj,targetKeys){
targetKeys.map(targetKey =>{
for(let key in _obj){
if(key === targetKey.oldKey){
_obj[targetKey.newKey] = _obj[key]
Reflect.deleteProperty(_obj, key)
if(targetKey.type === 'Array' && _obj[targetKey.newKey].length > 0){
_obj[targetKey.newKey].map(res =>{
changeKey(res,targetKeys)
})
}
}
}
})
}
// 调用
const needObj = replaceField(targetObj,targetKeys)
结尾
当然这绝不是最佳方案,如果有更优雅,更高效的方式,欢迎大神评论~~~