Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

golang: Marshal []os.FileInfo into JSON

Tags:

json

go

Basically, what I want to achieve is to get the content of a directory via os.ReadDir() and then encode the result into json.

Directly doing json.Marshal() cause no exception but gave me an empty result.

So I tried this:

func (f *os.FileInfo) MarshalerJSON() ([]byte, error) {
    return f.Name(), nil
}

Then Go tells me that os.FileInfo() is an interface and cannot be extended this way.

What's the best way to do this?

like image 419
lang2 Avatar asked Mar 18 '23 13:03

lang2


2 Answers

Pack the data into a struct that can be serialized:

http://play.golang.org/p/qDeg2bfik_

type FileInfo struct {
    Name    string
    Size    int64
    Mode    os.FileMode
    ModTime time.Time
    IsDir   bool
}

func main() {
    dir, err := os.Open(".")
    if err != nil {
        log.Fatal(err)
    }
    entries, err := dir.Readdir(0)
    if err != nil {
        log.Fatal(err)
    }

    list := []FileInfo{}

    for _, entry := range entries {
        f := FileInfo{
            Name:    entry.Name(),
            Size:    entry.Size(),
            Mode:    entry.Mode(),
            ModTime: entry.ModTime(),
            IsDir:   entry.IsDir(),
        }
        list = append(list, f)
    }

    output, err := json.Marshal(list)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(string(output))

}
like image 149
JimB Avatar answered Mar 28 '23 13:03

JimB


Here is a different version that makes the usage seemingly simple. Though you cannot unmarshall it back to the object. This is only applicable if you are sending it to client-end or something.

http://play.golang.org/p/vmm3temCUn

Usage

output, err := json.Marshal(FileInfo{entry})    

output, err := json.Marshal(FileInfoList{entries})

Code

type FileInfo struct {
    os.FileInfo
}

func (f FileInfo) MarshalJSON() ([]byte, error) {
    return json.Marshal(map[string]interface{}{
        "Name":    f.Name(),
        "Size":    f.Size(),
        "Mode":    f.Mode(),
        "ModTime": f.ModTime(),
        "IsDir":   f.IsDir(),
    })
}

type FileInfoList struct {
    fileInfoList []os.FileInfo
}

//This is inefficient to call multiple times for the same struct
func (f FileInfoList) MarshalJSON() ([]byte, error) {
    fileInfoList := make([]FileInfo, 0, len(f.fileInfoList))
    for _, val := range f.fileInfoList {
        fileInfoList = append(fileInfoList, FileInfo{val})
    }

    return json.Marshal(fileInfoList)
}
like image 31
Gnani Avatar answered Mar 28 '23 11:03

Gnani