递归地将数组转换为特定格式



我有一个包含分层数据的数组,我想将其转换为层次结构,但格式不同。我尝试使用递归方法,但它没有提供正确的数据

下面是我试图实现的代码

static convertConfigJson(data, finalResults = []) {
const configData = JSON.parse(JSON.stringify(data));
return configData.map((item) => {
const { name, type, value, path } = item;
let children = {}
if (type === 'Object') {
children = this.convertConfigJson(value, finalResults);
} else {
finalResults.push({
id: name,
name: name,
children: children
})
}


console.log('>>>>>>>>>', finalResults)
return finalResults;
});   
}

下面是我从 API 获得的 JSON 数组

[
{
"name": "info",
"type": "Object",
"value": [
{
"name": "app",
"type": "Object",
"value": [
{
"path": "info.app",
"name": "encoding",
"type": "TEXT",
"value": "@project.build.sourceEncoding@"
},
{
"name": "java",
"type": "Object",
"value": [
{
"path": "info.app.java",
"name": "source",
"type": "TEXT",
"value": "@java.version@"
},
{
"path": "info.app.java",
"name": "target",
"type": "TEXT",
"value": "java.version@"
}
]
}
]
}
]
}
]

我想将上面的数组转换为以下格式,即将值数组更改为子数组

[
{
"name": "info",
"type": "Object",
"children": [
{
"name": "app",
"type": "Object",
"children": [
{
"path": "info.app",
"name": "encoding",
"type": "TEXT",
"value": "@project.build.sourceEncoding@"
},
{
"name": "java",
"type": "Object",
"children": [
{
"path": "info.app.java",
"name": "source",
"type": "TEXT",
"value": "@java.version@"
},
{
"path": "info.app.java",
"name": "target",
"type": "TEXT",
"value": "java.version@"
}
]
}
]
}
]
}
]

对 child 属性中的所有元素进行简单的递归遍历。 将 .value 设置为 .children,然后删除 .value

walk = node => {
if(!node.value || typeof node.value!=='object') return
node.children = node.value
delete node.value
node.children.forEach(walk)
}
data.forEach(walk)
console.log(data)
<script>
data=[
{
"name": "info",
"type": "Object",
"value": [
{
"name": "app",
"type": "Object",
"value": [
{
"path": "info.app",
"name": "encoding",
"type": "TEXT",
"value": "@project.build.sourceEncoding@"
},
{
"name": "java",
"type": "Object",
"value": [
{
"path": "info.app.java",
"name": "source",
"type": "TEXT",
"value": "@java.version@"
},
{
"path": "info.app.java",
"name": "target",
"type": "TEXT",
"value": "java.version@"
}
]
}
]
}
]
}
]
</script>

transform方法,当任何对象的"值"类型是数组时,递归调用transform

const transform = ({ value, ...rest }) => {
const item = { ...rest };
Array.isArray(value)
? (item["children"] = value.map(transform))
: (item["value"] = value);
return item;
};
// Update: Based on @user120242 suggestion, creating another object is not required and using `Object.assign` will simplify.
const transform2 = ({ value, ...rest }) =>
Object.assign(
rest,
Array.isArray(value) ? { children: value.map(transform2) } : { value }
);
const items = [
{
name: "info",
type: "Object",
value: [
{
name: "app",
type: "Object",
value: [
{
path: "info.app",
name: "encoding",
type: "TEXT",
value: "@project.build.sourceEncoding@",
},
{
name: "java",
type: "Object",
value: [
{
path: "info.app.java",
name: "source",
type: "TEXT",
value: "@java.version@",
},
{
path: "info.app.java",
name: "target",
type: "TEXT",
value: "java.version@",
},
],
},
],
},
],
},
];
const output = items.map(transform);
console.log(output);
console.log(items.map(transform2));

此技术类似于 user120242 的答案,但它不会改变您的输入结构,而是创建一个新的输入结构:

const transform = ({value, ...rest}) => 
Array .isArray (value)
? {...rest, children: value .map (transform)}
: {...rest, value}
const data = [{name: "info", type: "Object", value: [{name: "app", type: "Object", value: [{path: "info.app", name: "encoding", type: "TEXT", value: "@project.build.sourceEncoding@"}, {name: "java", type: "Object", value: [{path: "info.app.java", name: "source", type: "TEXT", value: "@java.version@"}, {path: "info.app.java", name: "target", type: "TEXT", value: "java.version@"}]}]}]}]
console .log (data .map (transform))

更新

借用sivako的技术,我们可以很好地简化这一点:

const transform = ({value, ...rest}) => ({
... rest, 
... (Array .isArray (value) ? {children: value .map (transform)} : {value})
})
const data = [{name: "info", type: "Object", value: [{name: "app", type: "Object", value: [{path: "info.app", name: "encoding", type: "TEXT", value: "@project.build.sourceEncoding@"}, {name: "java", type: "Object", value: [{path: "info.app.java", name: "source", type: "TEXT", value: "@java.version@"}, {path: "info.app.java", name: "target", type: "TEXT", value: "java.version@"}]}]}]}]
console .log (data .map (transform))

最简单的方法是在字符串化后替换所有要"children": ["value": [

function convertConfigJson(data) {
const configData = JSON.parse(JSON.stringify(data).replace(/"value":[/g, '"children":['));
return configData
}

您也可以一一浏览嵌套对象的所有键,并将值键替换为值中的数组到子项

最新更新