如何根据JSONPath生成的属性和索引的字符串重命名对象键



很抱歉提出这个可能令人困惑的问题。我的意思是:

我的任务是重命名从XML转换而来的大量嵌套JSON对象上的一组特定对象键。这些关键点分散在嵌套对象中,同时隐藏在数组和对象下。让我告诉你我的意思:

const obj = {
"Zone": [
{
ExtWall: [
{ Win: "10" }
],
HVACDist: {
HVACCool: [
{ Win: "10" }
]
}
}
]
};

在这种情况下,我需要将键Win重命名为ResWin

var WinPath = jp.paths(object, '$..Win');
// Returns - [
//  [ '$', 'Zone', 0, 'ExtWall', 0, 'Win' ],
//  [ '$', 'Zone', 0, 'HVACDist', 'HVACCool', 0, 'Win' ]
// ]

JSONPath还有一个字符串函数,它根据生成的路径数组生成一个路径。现在让我们关注一个元素:

const pathStringified = jp.stringify(WinPath[0])
// Returns -  $['Zone'][0]['ExtWall][0]['Win']

不知怎么的,我需要将这个Win键重命名为ResWin

obj['Zone'][0]['ExtWall][0]['ResWin'] = obj['Zone'][0]['ExtWall][0]['Win'];
delete obj['Zone'][0]['ExtWall][0]['Win']; 

如有任何反馈或建议,我们将不胜感激。此外,让我知道如何重组我的问题,因为我可以理解它是如何难以理解的。

听起来你可以使用库,所以这里有一个使用对象扫描的解决方案。

.as-console-wrapper {max-height: 100% !important; top: 0}
<script type="module">
import objectScan from 'https://cdn.jsdelivr.net/npm/object-scan@18.3.11/lib/index.min.js';
const obj = { Zone: [{ ExtWall: [{ Win: '10' }], HVACDist: { HVACCool: [{ Win: '10' }] } }] };
const modify = objectScan(['**.Win'], {
filterFn: ({ parent, property, value }) => {
delete parent[property];
parent.ResWin = value;
},
rtn: 'count'
});
const r = modify(obj);
console.log(r); // number of matches
// => 2
console.log(obj);
// => { Zone: [ { ExtWall: [ { ResWin: '10' } ], HVACDist: { HVACCool: [ { ResWin: '10' } ] } } ] }
</script>

免责声明:我是物体扫描的作者

语法与JSONPath sytax非常相似,但它提供了回调。代码可以很容易地被生成,以允许在一次迭代中重命名多个键。

请注意,obj已在适当位置进行了修改。如果不需要,你可以在修改前进行复制(例如使用lodash cloneDeep(

如果您想用相同的名称替换所有键,您可以迭代整个树。如果你想按路径重命名,基本上是循环向下搜索路径,直到你到达请求的键。

const obj = {
"Zone": [{
ExtWall: [{
Win: "10"
}],
HVACDist: {
HVACCool: [{
Win: "10"
}]
}
}]
};
var WinPath = [
['$', 'Zone', 0, 'ExtWall', 0, 'Win'],
['$', 'Zone', 0, 'HVACDist', 'HVACCool', 0, 'Win']
];

function rename_by_path(obj, arr_path, new_name) {
var pointer = obj;
var dollar = arr_path.shift();
var key = arr_path.shift();
while (arr_path.length) {
pointer = pointer[key]
key = arr_path.shift();
}
pointer[new_name] = pointer[key]
delete pointer[key]
}

function rename_all(obj, key_name, new_name) {
const iterate = (obj) => {
if (!obj) {
return;
}
Object.keys(obj).forEach(key => {
var value = obj[key]
if (typeof value === "object" && value !== null) {
iterate(value)
}
if (key == key_name) {
obj[new_name] = value;
delete obj[key];
}
})
}
iterate(obj)
}

function rename_by_paths(obj, arr_paths, new_name) {
arr_paths.forEach(arr_path => rename_by_path(obj, arr_path, new_name))
}
rename_by_paths(obj, WinPath, "ResWin")
console.log(obj)
rename_all(obj, "ResWin", "ResWin2");
console.log(obj)
.as-console-wrapper {
max-height: 100% !important;
}

最新更新