如何在Go语言中将文件路径转换为JSON树形结构
解决Go语言中文件路径转嵌套JSON树形结构的问题
需求描述
需要将以下格式的文件路径列表转换为嵌套的JSON树形结构:
输入示例:
/home/aneesh/Code/GmailProject/main.py, 55 /home/aneesh/Code/Parser/parse.py, 66 /home/user/Project/image.png, 77 /home/user/Music/output.wav, 88
期望输出:
{ "home": { "aneesh": { "Code": { "GmailProject": { "main.py": 55 }, "Parser": { "parse.py": 66 } } }, "user": { "Project": { "image.png": 77 }, "Music": { "output.wav": 88 } } } }
问题难点
Go语言的类型系统不像Python那样灵活,无法直接使用多层嵌套的动态映射,map[string]int只能处理叶子节点,无法表示中间的目录节点(目录节点是map[string]interface{}类型),导致构建树形结构时遇到类型转换和嵌套修改的问题。
用户尝试的代码存在的核心问题:
package main import "fmt" func main() { l := "/home/aneesh/Code/Python/main.py" m := make(map[string]bool, 10) } func arrange(m *map[string]any, s string) { arr := strings.Split(s, "/")[1:] ma := *m for i, e := range arr { if i == len(arr)-1 { ma[e] = true } else { ma = ma[e] // 类型不匹配:ma[e]是bool类型,无法赋值给ma(map[string]any) } } }
解决思路
使用map[string]interface{}作为树形结构的通用节点类型,因为每个节点既可以是子目录(map[string]interface{}),也可以是文件对应的数值(int)。通过迭代路径分段逐步构建结构:
- 解析每一行输入,拆分出文件路径和对应的数值
- 从根节点开始,遍历路径的每一段
- 非最后一段(目录):检查当前节点是否存在该目录,不存在则创建新的
map[string]interface{}节点,存在则切换到该子节点 - 最后一段(文件):将当前节点的对应键赋值为解析出的数值
完整实现代码
package main import ( "encoding/json" "fmt" "strconv" "strings" ) func main() { // 模拟输入数据 inputLines := []string{ "/home/aneesh/Code/GmailProject/main.py, 55", "/home/aneesh/Code/Parser/parse.py, 66", "/home/user/Project/image.png, 77", "/home/user/Music/output.wav, 88", } // 根节点,用map[string]interface{}存储树形结构 root := make(map[string]interface{}) for _, line := range inputLines { // 拆分路径和数值部分 parts := strings.SplitN(line, ",", 2) if len(parts) != 2 { continue } path := strings.TrimSpace(parts[0]) valueStr := strings.TrimSpace(parts[1]) value, err := strconv.Atoi(valueStr) if err != nil { fmt.Printf("无效数值:%s\n", valueStr) continue } // 拆分路径为分段,去掉开头空字符串(因路径以/开头) segments := strings.Split(path, "/")[1:] if len(segments) == 0 { continue } // 从根节点开始遍历路径分段 current := root for i, seg := range segments { if i == len(segments)-1 { // 最后一段是文件,赋值对应数值 current[seg] = value } else { // 非最后一段是目录,检查是否存在 node, exists := current[seg] if !exists { // 不存在则创建新的目录节点 newNode := make(map[string]interface{}) current[seg] = newNode current = newNode } else { // 存在则转换为map类型,继续深入 childMap, ok := node.(map[string]interface{}) if !ok { fmt.Printf("路径冲突:%s 不是目录\n", seg) break } current = childMap } } } } // 生成格式化的JSON输出 jsonData, err := json.MarshalIndent(root, "", " ") if err != nil { fmt.Println("JSON序列化错误:", err) return } fmt.Println(string(jsonData)) }
代码说明
- 输入解析:拆分每行的路径与数值,将字符串数值转为整数
- 路径分段处理:拆分路径并过滤开头空字符串,避免无效节点
- 树形构建:动态创建目录节点,处理路径冲突(如目录与文件重名)
- JSON输出:使用
json.MarshalIndent生成可读性强的格式化JSON字符串
内容的提问来源于stack exchange,提问作者Aneesh Bhave
相关产品推荐
相关产品推荐

