Reputation: 77
Recently trying out Viper with my Cobra app to parse my config, but turned out that I couldn't parse the inner nested block. The map for ClustersOuter
is always empty, and I am sure the mapstructure is tagged correctly. I would prefer to use Viper Unmarshall feature rather than Getting the data type manually.
Output
map[zones:[{ClustersOuter:map[] Id:1} {ClustersOuter:map[] Id:2}]]
Somehow it seems like I can only retrieve the zone
map and its ID, but not any map for the clusters
map.
My inputs:
config.yml
zones:
- id: 1
clusters:
- cluster_id: 1
k3s_config_file: "k3s-cluster-1-config.yaml"
- cluster_id: 2
k3s_config_file: "k3s-cluster-2-config.yaml"
- cluster_id: 3
k3s_config_file: "k3s-cluster-3-config.yaml"
- id: 2
clusters:
- cluster_id: 1
k3s_config_file: "k3s-cluster-1-config.yaml"
- cluster_id: 2
k3s_config_file: "k3s-cluster-2-config.yaml"
- cluster_id: 3
k3s_config_file: "k3s-cluster-3-config.yaml"
configuration.go
package config
type Zones struct {
ClustersOuter map[string][]ClustersOuter `mapstructure:"zones"`
Id int `mapstructure:"id"`
}
type ClustersInner struct {
ClusterId int `mapstructure:"cluster_id"`
K3sConfigFile string `mapstructure:"k3s_config_file"`
}
type ClustersOuter struct {
ClustersInner map[string][]ClustersInner `mapstructure:"clusters"`
}
type ConfigSuper map[string][]Zones
main.go
viper.SetConfigName("config")
viper.AddConfigPath(".")
viper.SetConfigType("yaml")
if err := viper.ReadInConfig(); err != nil {
log.Fatalf("Error reading config file, %s", err)
return false
}
var configuration config.ConfigSuper
err := viper.Unmarshal(&configuration)
if err != nil {
log.Fatalf("unable to decode into struct, %v", err)
}
fmt.Printf("%+v\n", configuration)
Upvotes: 0
Views: 2796
Reputation: 1457
Your struct types do not reflect the YAML type, it looks like you've combined maps and slices together when you're only dealing with slices. In YAML, maps look like this:
myMap:
key1: value1
and arrays look like this:
myArray:
- foo: bar
Unfortunately, your config object is messed up enough that I can't understand the intent so I re-wrote it for you. These types can be decoded by Viper without any issues.
type Config struct {
Zones []Zone `mapstructure:"zones"`
}
type Zone struct {
ID int `mapstructure:"id"`
Clusters []Cluster `mapstructure:"clusters"`
}
type Cluster struct {
ClusterID int `mapstructure:"cluster_id"`
K3sConfigFile string `mapstructure:"k3s_config_file"`
}
The Config
struct is the root object, make sure to unmarshal into that.
config := Config{}
err = viper.Unmarshal(&config)
Upvotes: 3