如何将文件路径数组转换为层级JSON对象?
把扁平路径数组转成嵌套层级JSON的实现方案
嘿,这个需求很典型——把一堆扁平的文件路径转成带层级的JSON结构,重点要处理同一个目录下既有子文件夹又有直接文件的情况(比如你例子里的path2/subpath2)。我来给你一步步讲清楚怎么实现,用JavaScript为例,思路换其他语言也通用。
核心思路拆解
- 拆分路径片段:把每个路径按
/拆成目录和文件名的数组,比如path2/subpath2/additionalpath1/file1.doc会变成["path2", "subpath2", "additionalpath1", "file1.doc"]。 - 逐层构建层级:从根对象开始,顺着每个片段往下走:
- 如果遇到的是目录片段,就检查当前层级有没有这个目录:没有就创建空对象;如果之前这个位置是文件数组(说明原来只有直接文件),就把数组转成带
files字段的对象,再继续往下。 - 如果遇到的是文件名,就看当前层级的类型:如果是数组就直接加进去;如果是对象(有子目录)就加到
files数组里。
- 如果遇到的是目录片段,就检查当前层级有没有这个目录:没有就创建空对象;如果之前这个位置是文件数组(说明原来只有直接文件),就把数组转成带
- 最后整理格式:把那些只有
files字段的目录对象转成纯数组(比如path1/subpath1不需要{files: [...]},直接用数组就行)。
完整代码实现
function pathsToHierarchy(paths) { const root = {}; // 遍历所有路径,构建初始层级 paths.forEach(path => { const parts = path.split('/'); let currentNode = root; // 先处理所有目录层级(除了最后一个文件名) for (let i = 0; i < parts.length - 1; i++) { const dirName = parts[i]; // 如果当前节点下没有这个目录,创建空对象 if (!currentNode[dirName]) { currentNode[dirName] = {}; } // 如果原来这个位置是文件数组,要转成带files的对象(因为现在要加子目录) else if (Array.isArray(currentNode[dirName])) { currentNode[dirName] = { files: currentNode[dirName] }; } // 进入下一层目录 currentNode = currentNode[dirName]; } // 处理最后一个部分:文件名 const fileName = parts[parts.length - 1]; if (Array.isArray(currentNode)) { // 当前层级是文件数组,直接添加 if (!currentNode.includes(fileName)) { currentNode.push(fileName); } } else if (typeof currentNode === 'object') { // 当前层级是目录对象,用files数组存直接文件 if (!currentNode.files) { currentNode.files = []; } if (!currentNode.files.includes(fileName)) { currentNode.files.push(fileName); } } else { // 当前层级为空,初始化为文件数组 currentNode = [fileName]; } }); // 整理格式:把只有files属性的对象转成纯数组 function cleanUpNode(node) { if (typeof node === 'object' && !Array.isArray(node)) { const keys = Object.keys(node); // 如果对象只有files这一个键,就直接返回files数组 if (keys.length === 1 && keys[0] === 'files') { return node.files; } // 递归处理每个子节点 for (const key in node) { node[key] = cleanUpNode(node[key]); } } return node; } return cleanUpNode(root); } // 测试你的路径数组 const inputPaths = [ "path1/subpath1/file1.doc","path1/subpath1/file2.doc", "path1/subpath2/file1.doc","path1/subpath2/file2.doc", "path2/subpath1/file1.doc","path2/subpath1/file2.doc", "path2/subpath2/file1.doc","path2/subpath2/file2.doc", "path2/subpath2/additionalpath1/file1.doc" ]; const result = pathsToHierarchy(inputPaths); // 输出格式化后的JSON console.log(JSON.stringify(result, null, 2));
运行结果
执行上面的代码后,你会得到完全符合需求的JSON结构:
{ "path1": { "subpath1": ["file1.doc", "file2.doc"], "subpath2": ["file1.doc", "file2.doc"] }, "path2": { "subpath1": ["file1.doc", "file2.doc"], "subpath2": { "additionalpath1": ["file1.doc"], "files": ["file1.doc", "file2.doc"] } } }
关键细节说明
- 为什么需要
cleanUpNode函数?因为当一个目录下只有直接文件、没有子目录时,我们希望用数组而不是带files的对象来表示(比如path1/subpath1),这个函数就是做这个转换的。 - 处理“既有文件又有子目录”的情况:比如
path2/subpath2,当我们先添加了file1.doc和file2.doc,后来又添加additionalpath1/file1.doc时,会自动把原来的文件数组转成带files的对象,再添加子目录。
内容的提问来源于stack exchange,提问作者Shakthi
相关产品推荐
相关产品推荐

