求通用JavaScript/TypeScript函数去除JSON深层嵌套结构
通用JSON嵌套展开函数实现
需求说明
需要编写一个通用的JavaScript/TypeScript函数,能够将JSON中存在深层嵌套的父键(如示例中的categories)展开为同级键值对,同时保留其他字段的原有结构。该函数需具备通用性,可处理任意类似categories这种多层嵌套的场景。
嵌套示例JSON
const nestedObject = { "code": { "prev": [], "current": null }, "updatedAt": { "prev": "2024-05-22T12:33:38.834Z", "current": "2024-05-23T08:47:11.151Z" }, "categories": { "5": { "prev": null, "current": { "id": 12, "name": "Value-1" } }, "6": { "prev": null, "current": { "id": 13, "name": "Value-2" } }, "7": { "prev": null, "current": { "id": 14, "name": "Value-3" } }, "25": { "24": { "23": { "22": { "21": { "20": { "19": { "18": { "prev": null, "current": { "id": 25, "name": "Value-3" } }, "prev": null, "current": { "id": 26, "name": "Value-4" } }, "prev": null, "current": { "id": 27, "name": "Value-5" } }, "prev": null, "current": { "id": 28, "name": "Value-6" } }, "prev": null, "current": { "id": 29, "name": "Value-7" } }, "prev": null, "current": { "id": 30, "name": "Value-8" } }, "prev": null, "current": { "id": 31, "name": "Value-9" } }, "prev": null, "current": { "id": 32, "name": "Value-10" } } } };
期望输出结果
const expectedOutput = { "code": { "prev": [], "current": null }, "updatedAt": { "prev": "2024-05-22T12:33:38.834Z", "current": "2024-05-23T08:47:11.151Z" }, "categories": { "5": { "prev": null, "current": { "id": 12, "name": "Value-1" } }, "6": { "prev": null, "current": { "id": 13, "name": "Value-2" } }, "7": { "prev": null, "current": { "id": 14, "name": "Value-3" } }, "18": { "prev": null, "current": { "id": 25, "name": "Value-3" } }, "19": { "prev": null, "current": { "id": 26, "name": "Value-4" } }, "20": { "prev": null, "current": { "id": 27, "name": "Value-5" } }, "21": { "prev": null, "current": { "id": 28, "name": "Value-6" } }, "22": { "prev": null, "current": { "id": 29, "name": "Value-7" } }, "23": { "prev": null, "current": { "id": 30, "name": "Value-8" } }, "24": { "prev": null, "current": { "id": 31, "name": "Value-9" } }, "25": { "prev": null, "current": { "id": 32, "name": "Value-10" } } } };
现有问题函数
之前尝试的扁平化函数会将所有嵌套结构完全打散为键路径形式,无法满足保留非目标字段结构、仅展开指定类型嵌套的需求:
const flattenObject = (obj, prefix = '') => { let result = {}; for (let key in obj) { if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) { const nested = flattenObject(obj[key], `${prefix}${key}.`); result = { ...result, ...nested }; } else { result[`${prefix}${key}`] = obj[key]; } } return result; };
解决方案函数
以下是符合需求的通用函数,通过递归遍历判断节点类型:若节点包含prev和current则直接保留,否则继续提取嵌套子节点,最终将所有有效节点整理为同级结构:
type NestedNode = { prev?: any; current?: any; [key: string]: NestedNode | any; }; // 展开单个字段下的深层嵌套 const expandNestedObject = (obj: Record<string, any>): Record<string, any> => { const result: Record<string, any> = {}; for (const key in obj) { if (!obj.hasOwnProperty(key)) continue; const value = obj[key]; // 判断是否为包含prev/current的最终节点 if (typeof value === 'object' && value !== null && !Array.isArray(value)) { if ('prev' in value && 'current' in value) { result[key] = value; } else { // 递归展开并合并结果 const expanded = expandNestedObject(value); Object.assign(result, expanded); } } else { result[key] = value; } } return result; }; // 处理整个JSON对象,对所有对象类型字段执行展开 const processNestedJson = (json: Record<string, any>): Record<string, any> => { const processed = {...json}; for (const key in processed) { if (typeof processed[key] === 'object' && processed[key] !== null && !Array.isArray(processed[key])) { processed[key] = expandNestedObject(processed[key]); } } return processed; };
使用示例
const output = processNestedJson(nestedObject); console.log(output); // 输出与expectedOutput一致
内容的提问来源于stack exchange,提问作者Waqar Ali
相关产品推荐
相关产品推荐

