javascript - 用 JS 递归转换我的 JSON 数据
问题描述
我试图弄清楚如何转换我从 Web 服务返回的一些 JSON,以便我可以轻松地将其解析为一个很好的类型安全对象。我想将此格式转换为:
[{
"name": "AwesomePeople",
"value": [
[{
"name": "TypeId",
"value": 1
}, {
"name": "People",
"value": [
[{
"name": "id",
"value": 2
}, {
"name": "name",
"value": "Danno"
}
],
[{
"name": "id",
"value": 3
}, {
"name": "name",
"value": "Julio"
}
]
]
}
],
[{
"name": "TypeId",
"value": 2
}, {
"name": "People",
"value": [
[{
"name": "id",
"value": 4
}, {
"name": "name",
"value": "Jenna"
}
],
[{
"name": "id",
"value": 5
}, {
"name": "name",
"value": "Coolio"
}
]
]
}
]
]
}
]
转为以下格式:
[{
"AwesomePeople": [
[{
"TypeId": 1,
}, {
"People": [
[{
"id": 2
}, {
"firstName":"Danno"
}
],
[{
"id": 3,
}, {
"firstName": "Julio"
}
]
]
}
],
[{
"TypeId": 2
}, {
"People": [
[{
"id": 4
}, {
"firstName": "Jenna"
}
],
[{
"id": 5
}, {
"firstName": "Coolio"
}
]
]
}
]
]
}
];
需要发生两件主要的事情,这些愚蠢的“名称”/“值”对需要在任何和所有级别进行交换。例如,不是“name”:“id”、“value”:“3”,而是“id”:3。这些值有时是数组,所以它们需要以类似的方式处理......深度是可变的,所以我不能假设一定数量的深度,所以我需要继续递归处理所有内容。
我已经开始使用下面的代码......你会看到一个空的“newResult”数组,当我遍历原始 JSON 时,我正在尝试构建它,无论我当前正在查看一个对象还是一个数组,都会采取不同的操作,或密钥/属性。
let count = 0;
let result = <the original array above>
let newResult = [];
result.forEach(function(resObj) {
console.log("STARTING to TRAVERSE HIGHER LEVEL OBJECTS!");
traverse(resObj);
count++;
//we're done processing high level objects, so return from this function and enjoy the newResult!
if (count===result.length)
//return from this function
console.log(newResult);
console.log("FINISHED PROCESSING HIGHER LEVEL OBJECTS, SO DONE!");
});
//Below are the functions for traversing
function traverse(x, level) {
if (isArray(x)) {
console.log("array");
traverseArray(x);
} else if ((typeof x === 'object') && (x !== null)) {
console.log("object");
traverseObject(x);
} else {
console.log("property: "+x);
//console.log(level + x);
}
}
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
function traverseArray(arr, level) {
//console.log(level + "<array>");
arr.forEach(function(x) {
traverse(x);
});
}
function traverseObject(obj, level) {
var keyName, keyValue;
//console.log(level + "<object>");
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (key==="name"){
keyName = obj[key];
}else if (key==="value"){
keyValue = obj[key];
}
if (keyName && keyValue){
var newObj = {[keyName]: keyValue}
newResult.push(newObj);
//console.log("the KEY NAME IS: "+ keyName + ", and the VALUE is: "+keyValue);
}
//if we have a key value, but the value is an array, stop and
// if (isArray(newOj)
console.log("traversing..." +obj[key]);
traverse(obj[key]);
}//end if property
}//end foreach key in object
}//end traverseObject
谢谢大家......感谢那些可以解决这个问题的人:)
解决方案
您可以使用JSON.stringify
and JSON.parse
- 使用 reviver 执行此操作,检查该值是否具有name
属性,如果有,则返回{ [value.name]: value.value }
:
const arr=[{name:"AwesomePeople",value:[[{name:"TypeId",value:1},{name:"People",value:[[{name:"id",value:2},{name:"name",value:"Danno"}],[{name:"id",value:3},{name:"name",value:"Julio"}]]}],[{name:"TypeId",value:2},{name:"People",value:[[{name:"id",value:4},{name:"name",value:"Jenna"}],[{name:"id",value:5},{name:"name",value:"Coolio"}]]}]]}];
const result = JSON.parse(JSON.stringify(arr, (key, value) => (
value?.name
? { [value.name]: value.value }
: value
)));
console.log(result);
如果您还想将name
值更改为firstName
键,请在计算属性中添加条件:
const arr=[{name:"AwesomePeople",value:[[{name:"TypeId",value:1},{name:"People",value:[[{name:"id",value:2},{name:"name",value:"Danno"}],[{name:"id",value:3},{name:"name",value:"Julio"}]]}],[{name:"TypeId",value:2},{name:"People",value:[[{name:"id",value:4},{name:"name",value:"Jenna"}],[{name:"id",value:5},{name:"name",value:"Coolio"}]]}]]}];
const result = JSON.parse(JSON.stringify(arr, (key, value) => (
value?.name
? { [value.name === 'name' ? 'firstName' : value.name]: value.value }
: value
)));
console.log(result);
手动:
const arr=[{name:"AwesomePeople",value:[[{name:"TypeId",value:1},{name:"People",value:[[{name:"id",value:2},{name:"name",value:"Danno"}],[{name:"id",value:3},{name:"name",value:"Julio"}]]}],[{name:"TypeId",value:2},{name:"People",value:[[{name:"id",value:4},{name:"name",value:"Jenna"}],[{name:"id",value:5},{name:"name",value:"Coolio"}]]}]]}];
const recurse = (val) => {
if (!val || typeof val !== 'object') return val;
if (Array.isArray(val)) return val.map(recurse);
return { [val.name === 'name' ? 'firstName' : val.name]: val.value };
};
const result = recurse(arr);
console.log(result);
推荐阅读
- azure - 使用 Azure DevOps Pipeline 部署 Bot Framework 解决方案
- linux - 为什么我的屏幕会话在服务器启动过程中终止?
- c++ - 使用 __func__ 标识符时的 C++ 访问冲突读取位置 0xFFFFFFFFFFFFFFFF
- python - 如何使用回调在 Python 中使用 Dash 添加到存储在 Div 中的字符串?
- node.js - 仅包含与另一条路径的值相关的 Mongoose 模式的路径
- python - 散景在按钮按下时将图形添加到布局
- angular - 在 Angular 7 中访问 Trix 配置
- cors - 尝试将 AMP 表单提交到 Azure Logic 应用时出现 CORS 错误
- vue.js - nicolasbeauvais/vue-social-sharing 使用这个包并想要制作动态标题、描述、报价、标签
- dplyr - ifelse 返回意外的值