goconfigurationviper

How to get a configuration array of objects using viper in golang?


I have a config file that looks like:

{
    "auth": {
        "client_id": "foo",
        "client_secret": "bar",
        "account": "foo@bar.com",
        "secrets_type": "auto"
    },
    "jobs": [
    {
        "source_folder": "folder1",
        "create_albums": "off",
        "delete_after_upload": false,
        "include": [
            "*.jpg"
        ],
        "exclude": []
    },
    {
        "source_folder": "folder2",
        "create_albums": "folderName",
        "delete_after_upload": true,
        "include": [
            "*.jpg", "*.webp"
        ],
        "exclude": [
            "abc*"
        ]
    }   
    ]
}

And I'm reading it using the viper package in golang.

I'm having problems to get the jobs settings:

    type FolderUpload struct {
        sourceFolder      string   `mapstructure:"source_folder"`
        createAlbums      string   `mapstructure:"create_albums"`
        deleteAfterUpload bool     `mapstructure:"delete_after_upload"`
        include           []string `mapstructure:"include"`
        exclude           []string `mapstructure:"exclude"`
    }

    // Read the "jobsSettings" section as a slice of maps
    jobsSettings := viper.Get("jobs").([]interface{})

    // Iterate over each job item
    for _, job := range jobsSettings {
        jobMap := job.(map[string]interface{})

        j := FolderUploadJob{
            sourceFolder:      jobMap["source_folder"].(string),
            createAlbums:      jobMap["create_albums"].(string),
            deleteAfterUpload: jobMap["delete_after_upload"].(bool),
            include:           jobMap["include"].([]string),
            exclude:           jobMap["exclude"].([]string),
        }
    }

I've tried with viper.UnmarshalKey() too, but I always receive a panic when trying to read the include and exclude.

Can anyone point me to the right way?


Solution

  • viper.UnmarshalKey works and please note that the fields of FolderUpload should be exported. See the demo below:

    package main
    
    import (
        "fmt"
        "strings"
    
        "github.com/spf13/viper"
    )
    
    func main() {
        viper.SetConfigType("json")
    
        jsonConfig := `
    {
        "jobs": [
        {
            "source_folder": "folder1",
            "create_albums": "off",
            "delete_after_upload": false,
            "include": [
                "*.jpg"
            ],
            "exclude": []
        },
        {
            "source_folder": "folder2",
            "create_albums": "folderName",
            "delete_after_upload": true,
            "include": [
                "*.jpg", "*.webp"
            ],
            "exclude": [
                "abc*"
            ]
        }
        ]
    }`
    
        type FolderUpload struct {
            SourceFolder      string   `mapstructure:"source_folder"`
            CreateAlbums      string   `mapstructure:"create_albums"`
            DeleteAfterUpload bool     `mapstructure:"delete_after_upload"`
            Include           []string `mapstructure:"include"`
            Exclude           []string `mapstructure:"exclude"`
        }
    
        if err := viper.ReadConfig(strings.NewReader(jsonConfig)); err != nil {
            panic(err)
        }
        var jobs []FolderUpload
    
        if err := viper.UnmarshalKey("jobs", &jobs); err != nil {
            panic(err)
        }
    
        fmt.Printf("%+v\n", jobs)
    }