0

I'm using viper to manage the configurations and environment variables for a Go app .
all of values are coming correct from the json config file expect the bool values are always coming false even it have a true value within the json file

{
  "database" : {
    "host" : "localhost",
    "port": "3306"
  },
  "host": "localhost",
  "port": ":3000",
  "production": true,
  "cache": true
}

the configuration package

package config

import (
    "github.com/spf13/viper"
    "html/template"
    "log"
)

type ViperConfig struct {
    Database struct {
        Host string "json:'host'"
        Port string "json:'port'"
    } "json:'database'"
    Host          string "json:'host'"
    Port          string "json:'port'"
    ProductionMod bool   "json:'production'"
    UseCache      bool   "json:'cache'"
    TemplaCache   map[string]*template.Template
}

func LoadConfig(path string) (viperconfig ViperConfig, err error) {
    viper.AddConfigPath(path)
    viper.SetConfigName("config")
    viper.SetConfigType("json")
    viper.AutomaticEnv()
    err = viper.ReadInConfig()
    if err != nil {
        log.Fatal("Can't load config file")
    }
    err = viper.Unmarshal(&viperconfig)
    return
}

all of this are working file when i tried to access any string but when tried to access the bool variables it always give false

package main

import (
    "github.com/alexedwards/scs/v2"
    "github.com/fouad82/news-api/cmd/config"
    "github.com/fouad82/news-api/cmd/routes"
    "log"
    "net/http"
    "time"
)

func main() {
    ViperConfig, err := config.LoadConfig("../")
    if err != nil {
        log.Fatal("Can't read viper configurations", err)
    }
    if err != nil {
        log.Fatal("Error Parsing template", err)
    }
    session := scs.New()
    session.Lifetime = 24 * time.Hour
    session.Cookie.Persist = true
    session.Cookie.SameSite = http.SameSiteLaxMode
    session.Cookie.Secure = ViperConfig.ProductionMod
    routes.Routes()
    // the values never gives the actuall value it always gives false
    log.Fatal(ViperConfig.UseCache, ViperConfig.ProductionMod)
    http.ListenAndServe(ViperConfig.Port, nil)
}

 
Marco
  • 842
  • 6
  • 18
  • 42

1 Answers1

2

First the json tags are written wrong.

I think viper doesn't use json tags. It uses the mapstructure tags. The other variables are working because the name of the variable is the same mapped on the json tags. (check this https://github.com/spf13/viper#unmarshaling)

2 solutions:

First: change the variables name


type ViperConfig struct {
    Database struct {
        Host string `json:"host"`
        Port string `json:"port"`
    } `json:"database"`
    Host          string `json:"host"`
    Port          string `json:"port"`
    Production bool   `json:"production"`
    Cache      bool   `json:"cache"`
    TemplaCache   map[string]*template.Template
}

Or use mapstructure tags



type ViperConfig struct {
    Database struct {
        Host string `json:"host"`
        Port string `json:"port"`
    } `json:"database"`
    Host          string `json:"host"`
    Port          string `json:"port"`
    ProductionMod bool   `json:"production" mapstructure:"production"`
    UseCache      bool   `json:"cache" mapstructure:"cache"`
    TemplaCache   map[string]*template.Template
}

Lucas Katayama
  • 4,445
  • 27
  • 34
  • it uses json tags from viper documentation reading from JSON, TOML, YAML, HCL, envfile and Java properties config files – Marco Jul 15 '21 at 21:21
  • No... read troubleshooting https://github.com/spf13/viper/blob/master/TROUBLESHOOTING.md#unmarshaling-doesnt-work – Lucas Katayama Jul 16 '21 at 00:08
  • "The most common reason for this issue is improper use of struct tags (eg. yaml or json). Viper uses github.com/mitchellh/mapstructure under the hood for unmarshaling values which uses mapstructure tags by default. Please refer to the library's documentation for using other struct tags. " – Lucas Katayama Jul 16 '21 at 00:08