
本文介绍如何使用递归 + Object.keys() 动态提取布尔型权限字段,将任意深度的嵌套权限 JSON 自动转换为目标对象结构,无需硬编码权限键名,支持未来灵活扩展。
本文介绍如何使用递归 + `object.keys()` 动态提取布尔型权限字段,将任意深度的嵌套权限 json 自动转换为目标对象结构,无需硬编码权限键名,支持未来灵活扩展。
在权限管理系统中,后端常返回嵌套的 JSON 结构(如模块级 + 子模块级权限),而前端组件(如权限树、配置表单)往往需要扁平、键值明确、可枚举的对象格式。手动维护权限字段列表(如 ['view', 'add', 'edit', 'delete', 'print'])不仅冗余,更违背开闭原则——一旦新增权限类型(如 'export': true 或 'audit': false),就必须同步修改多处代码。
理想的解决方案应具备动态性与递归性:自动识别所有值为 true 的布尔属性作为权限项,并对 permission_details(或任意含子项的字段)递归处理,同时保持语义清晰的键名(如 "Manufacture" → "manufacture")。
以下是推荐的生产就绪实现:
/**
* 将嵌套权限 JSON 递归转换为目标对象格式
* @param {Array} list - 待转换的权限数组(支持 module/sub_module 顶层对象)
* @returns {Object} 转换后的嵌套对象,键为小写下划线格式,值含 label、permissions、child(可选)
*/
const transformPermissions = (list) => {
if (!Array.isArray(list)) return {};
return list.reduce((acc, item) => {
// 确定当前层级的显示标签和主键名
const label = item.module ?? item.sub_module;
if (!label) return acc;
const key = label.toLowerCase().replace(/\s+/g, '_');
// 动态提取所有值为 true 的布尔字段(排除 id、rowId、sub_module、module、permission_details 等非权限字段)
const permissionKeys = Object.keys(item)
.filter(key =>
typeof item[key] === 'boolean' &&
item[key] === true &&
!['id', 'rowId', 'module', 'sub_module', 'permission_details'].includes(key)
);
// 构建当前节点
acc[key] = {
label,
permissions: permissionKeys,
...(item.permission_details && Array.isArray(item.permission_details) && item.permission_details.length > 0
? { child: transformPermissions(item.permission_details) }
: {})
};
return acc;
}, {});
};
// 使用示例
const result = transformPermissions(data.permissions_list);
console.log(result);✅ 核心优势说明:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
立即学习“Java免费学习笔记(深入)”;
- 完全动态识别权限字段:不依赖硬编码数组,通过 typeof item[key] === 'boolean' && item[key] === true 自动捕获所有启用的权限,新增字段(如 "export": true)零改造生效;
- 安全过滤元数据字段:显式排除 id、rowId、module、sub_module、permission_details 等非权限属性,避免误入权限列表;
- 健壮的递归逻辑:仅当 permission_details 存在且为非空数组时才递归调用,防止 undefined 或空数组导致异常;
- 语义化键名生成:使用正则 /\s+/g 替换所有空白字符(含多个空格、制表符),确保 "Formula Template" → "formula_template" 稳定可靠。
⚠️ 注意事项:
- 若原始数据中存在其他布尔型业务字段(如 "enabled": true, "active": false),需将其加入过滤白名单(如扩展 !['id', 'rowId', 'enabled', 'active', ...].includes(key)),避免混入权限数组;
- 当前逻辑默认 label 优先取 module,次取 sub_module,符合示例结构;若实际数据存在其他标签字段(如 name),可按需调整 label = item.module ?? item.sub_module ?? item.name;
- 输出结构中 child 始终为对象(非数组),符合目标格式要求;若需兼容数组形式(如用于 Vue/React 列表渲染),可在调用方做二次映射。
该方案兼顾简洁性、可维护性与扩展性,是处理动态权限结构的通用范式。

















