简体   繁体   中英

How to build recursive slices of structs in Go?

I need to create a JSON payload from a slice of strings. They represent the path to an individual file. They need to be merged together into final JSON payload representing the whole directory structure.

If the strings are below:

[
    "alpha/file1.json"
    "alpha/beta/file2.json"
    "alpha/beta/charlie/file3.json"
    "alpha/beta/charlie/file4.json"
    "delta/file5.json
]

JSON Payload Structure

  • A Directory struct should include a name, with either Children and/or Files.
  • Children will represent another Directory struct with it's own files
  • Files represents the file(s) inside the Directory

The JSON payload would be this:

[{
    "Name": "alpha",
    "Files": [{
        "Name": "file1.json",
        "Path": "alpha/file1.json"
    }],
    "Children": [{
        "Name": "beta",
        "Files": [{
            "Name": "file2.json",
            "Path": "alpha/beta/file2.json"
        }],
        "Children": [{
            "Name": "charlie",
            "Files": [{
                "Name": "file3.json",
                "Path": "alpha/beta/charlie/file3.json"
            },
            {
                "Name": "file4.json",
                "Path": "alpha/beta/charlie/file4.json"
            }]
        }]
    }]
},{
    "Name": "delta",
    "Files": [
        {
            "Name": "file5.json",
            "Path": "delta/file5.json"
        }
    ]
}]

I can't figure out how to look to determine if the directory name already exists and pass the pointer to that directory if it does. Currently, it appends a new directory structure to the base slice for each file path. Below is what I've got so far.

https://play.golang.org/p/WoNEcJLe51z

I needed to create a function which would return the index of the existing folder in the slice. Then recurse its Children.

// DirectoryStructure stores the directory structure
type DirectoryStructure struct {
    Name     string               `json:"Name"`
    Children []DirectoryStructure `json:"Children,omitempty"`
    Files    []File               `json:"Files,omitempty"`
}

// File stores the name of file and path to file
type File struct {
    Name string `json:"Name"`
    Path string `json:"Path"`
}

func main() {
    // Build slice of strings
    filePaths := []string{}
    filePaths = append(filePaths, "alpha/file1.json")
    filePaths = append(filePaths, "alpha/beta/file2.json")
    filePaths = append(filePaths, "alpha/beta/charlie/file3.json")
    filePaths = append(filePaths, "alpha/beta/charlie/file4.json")
    filePaths = append(filePaths, "delta/file5.json")

    // Create directory with slice of structs
    directory := []DirectoryStructure{}

    // Iterate through slice
    for _, path := range filePaths {
        pathSlice := strings.Split(path, "/")
        // Start recursive function. Passing directory and assigning it to itself
        directory = buildDirectory(pathSlice, path, directory)
    }

    b, err := json.Marshal(directory)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(string(b))
}

func buildDirectory(path []string, key string, directory []DirectoryStructure) []DirectoryStructure {
    // Return index of folder if it already exists.
    folderIndex := doesExist(path[0], directory)
    // If folder exists and the next value in the path slice is not the file
    if folderIndex > -1 && len(path) != 2 {
        // Pass existing folder's Children to buildDirectory function and assign to itself
        directory[folderIndex].Children = buildDirectory(path[1:], key, directory[folderIndex].Children)
        return directory
    }
    // If next value in the path slice is a file
    if len(path) == 2 {
        // If folder does not exist
        if folderIndex == -1 {
            // Create new folder with files inside and append to directory
            fileDirectory := DirectoryStructure{}
            fileDirectory.Files = []File{{path[1], string(key)}}
            fileDirectory.Name = path[0]
            directory = append(directory, fileDirectory)
        } else {
            // If folder does exist, append files to the directory
            directory[folderIndex].Files = append(directory[folderIndex].Files, File{path[1], string(key)})
        }
        return directory
    }
    // Folder does not exist and the next value is not a file
    // Create new directory, recurse it's Children, and append when returned
    currentDirectory := DirectoryStructure{}
    currentDirectory.Name = path[0]
    currentDirectory.Children = buildDirectory(path[1:], key, []DirectoryStructure{})
    directory = append(directory, currentDirectory)
    return directory

}

// doesExist returns index of folder if exists
func doesExist(folderName string, directory []DirectoryStructure) int {
    for index, element := range directory {
        if folderName == element.Name {
            return index
        }
    }
    return -1
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM