javascript - 扩展json关系JS的递归函数
问题描述
我有点卡在这个问题上:
我有这个 JSON:
[
{
"id": 1,
"name": "Sales",
"superdepartment": null
},
{
"id": 2,
"name": "Engineering",
"superdepartment": null
},
{
"id": 3,
"name": "Product",
"superdepartment": null
},
{
"id": 4,
"name": "Design",
"superdepartment": 3
},
{
"id": 5,
"name": "Inbound Sales",
"superdepartment": 1
},
{
"id": 6,
"name": "Outbound Sales",
"superdepartment": 1
},
{
"id": 7,
"name": "Application Security",
"superdepartment": 2
},
{
"id": 8,
"name": "Front-End",
"superdepartment": 2
},
{
"id": 9,
"name": "Sales Development",
"superdepartment": 6
},
{
"id": 10,
"name": "Product Management",
"superdepartment": 3
}
]
因此,我需要根据所需的级别递归地扩展“超级部门”关系。例如:
- 如果我将 ?expand=superdeparment 传递给我的端点,我需要打开 1 级关系
- 如果我通过 ?expand=superdepartment.superdepartment 我需要打开 2 个级别,这可以继续进行,所以我认为我需要一个递归解决方案。
实际上我有这个代码可以满足第一级,但是我在替换嵌套对象以打开第二个关系级别时遇到了几个问题。
department.js --> 在这里我获取数据(json)并调用“getRelations”方法。
module.exports.getAll = async function getAll(expand = null) {
let response = await data;
if (expand) {
response = modelUtils.getRelations(response, expand, response);
}
return response;
}
modelUtils.js --> 在这里我编写了核心函数来实现嵌套对象:
const _ = require('lodash');
//targetEntity is de JSON that I will use to get the nested entities from my actual ID.
// In this case is the same json, but can be another different.
module.exports.getRelations = function getRelations(entity, expand, targetEntity) {
let tmpEntity = _.cloneDeep(entity);
let path = expand.split('.');
for (let i=0; i < entity.length; i++) {
tmpEntity[i] = fillRelations(entity[i], path, targetEntity);
}
return tmpEntity;
}
function fillRelations(entity, path, targetEntity, level = 0) {
let current = _.cloneDeep(entity);
const currentPath = path[level];
if (!current[currentPath]) {
return current;
}
let value = targetEntity.filter(target => target.id === current[currentPath]);
if (value.length > 0) {
current[currentPath] = value[0];
}
level++;
return fillRelations(current, path, targetEntity, level);
}
所以实际上使用这段代码并将 ?expand=superdepartment.superdepartment 传递给我的端点,我得到了这个 JSON 响应:
[
{
"id": 1,
"name": "Sales",
"superdepartment": null
},
{
"id": 2,
"name": "Engineering",
"superdepartment": null
},
{
"id": 3,
"name": "Product",
"superdepartment": null
},
{
"id": 4,
"name": "Design",
"superdepartment": {
"id": 3,
"name": "Product",
"superdepartment": null
}
},
{
"id": 5,
"name": "Inbound Sales",
"superdepartment": {
"id": 1,
"name": "Sales",
"superdepartment": null
}
},
{
"id": 6,
"name": "Outbound Sales",
"superdepartment": {
"id": 1,
"name": "Sales",
"superdepartment": null
}
},
{
"id": 7,
"name": "Application Security",
"superdepartment": {
"id": 2,
"name": "Engineering",
"superdepartment": null
}
},
{
"id": 8,
"name": "Front-End",
"superdepartment": {
"id": 2,
"name": "Engineering",
"superdepartment": null
}
},
{
"id": 9,
"name": "Sales Development",
"superdepartment": {
"id": 6,
"name": "Outbound Sales",
"superdepartment": 1
}
},
{
"id": 10,
"name": "Product Management",
"superdepartment": {
"id": 3,
"name": "Product",
"superdepartment": null
}
}
]
如您所见,ID=9 元素需要为 id=1 打开第二级嵌套关系,因此它必须如下所示:
{
"id": 9,
"name": "Sales Development",
"superdepartment": {
"id": 6,
"name": "Outbound Sales",
"superdepartment": {
"id": 1,
"name": "Sales",
"superdepartment": null
}
}
},
解决方案
这是您问题的直接(和递归)解决方案:
const data = [{
"id": 1,
"name": "Sales",
"superdepartment": null
}, {
"id": 2,
"name": "Engineering",
"superdepartment": null
}, {
"id": 3,
"name": "Product",
"superdepartment": null
}, {
"id": 4,
"name": "Design",
"superdepartment": 3
}, {
"id": 5,
"name": "Inbound Sales",
"superdepartment": 1
}, {
"id": 6,
"name": "Outbound Sales",
"superdepartment": 1
}, {
"id": 7,
"name": "Application Security",
"superdepartment": 2
}, {
"id": 8,
"name": "Front-End",
"superdepartment": 2
}, {
"id": 9,
"name": "Sales Development",
"superdepartment": 6
}, {
"id": 10,
"name": "Product Management",
"superdepartment": 3
}
];
function compute(data, expand) {
const path = expand.split('.');
return data.map(x => attachEntities(x, data, path));
}
function attachEntities(obj, data, [prop, ...props]) {
return prop ? {
...obj,
[prop]: obj[prop] && attachEntities(data.find(y => y.id === obj[prop]) || obj[prop], data, props)
}
: obj;
}
console.log('One level', compute(data, 'superdepartment'));
console.log('Two levels', compute(data, 'superdepartment.superdepartment'));
console.log('Three levels', compute(data, 'superdepartment.superdepartment.superdepartment'));
推荐阅读
- php - 将 nodeValue 与 Switch Case 匹配
- java - JVM 如何为对象分配内存,尽管它们以后可能会变大
- json - 如何将类型 json 文件加载到 DropdownButton
- ios - iOS 使用 OC 通讯录右侧滑动检索波效果
- python-3.x - 布洛赫球中箭头的长度
- python - 如何在 FTP 服务器上检查目录中的更改?
- apache - Apache 服务器不允许 HTTP 请求中的授权标头
- excel - 在 OpenOffice Calc 中突出显示列中的重复值
- php - SQLSTATE [22007]:无效的日期时间格式:1366 不正确的整数值:第 1 行的列 'infraction_id' 的整数值:'["1","3","66","68"]'
- forms - 将在此 Flash 应用程序中工作的最大整数(从头开始)