在Viper中访问嵌套的YAML结构的问题

huangapple go评论142阅读模式
英文:

Problem accessing nested YAML structure in Viper

问题

最近我尝试使用Viper和我的Cobra应用程序一起解析配置文件,但是发现无法解析内部嵌套块。ClustersOuter的映射始终为空,我确定mapstructure的标签是正确的。我更喜欢使用Viper的Unmarshal功能而不是手动获取数据类型。

输出结果:

  1. map[zones:[{ClustersOuter:map[] Id:1} {ClustersOuter:map[] Id:2}]]

不知何故,我似乎只能获取zone映射及其ID,而无法获取clusters映射的任何内容。

我的输入:
config.yml

  1. zones:
  2. - id: 1
  3. clusters:
  4. - cluster_id: 1
  5. k3s_config_file: "k3s-cluster-1-config.yaml"
  6. - cluster_id: 2
  7. k3s_config_file: "k3s-cluster-2-config.yaml"
  8. - cluster_id: 3
  9. k3s_config_file: "k3s-cluster-3-config.yaml"
  10. - id: 2
  11. clusters:
  12. - cluster_id: 1
  13. k3s_config_file: "k3s-cluster-1-config.yaml"
  14. - cluster_id: 2
  15. k3s_config_file: "k3s-cluster-2-config.yaml"
  16. - cluster_id: 3
  17. k3s_config_file: "k3s-cluster-3-config.yaml"

configuration.go

  1. package config
  2. type Zones struct {
  3. ClustersOuter map[string][]ClustersOuter `mapstructure:"zones"`
  4. Id int `mapstructure:"id"`
  5. }
  6. type ClustersInner struct {
  7. ClusterId int `mapstructure:"cluster_id"`
  8. K3sConfigFile string `mapstructure:"k3s_config_file"`
  9. }
  10. type ClustersOuter struct {
  11. ClustersInner map[string][]ClustersInner `mapstructure:"clusters"`
  12. }
  13. type ConfigSuper map[string][]Zones

main.go

  1. viper.SetConfigName("config")
  2. viper.AddConfigPath(".")
  3. viper.SetConfigType("yaml")
  4. if err := viper.ReadInConfig(); err != nil {
  5. log.Fatalf("Error reading config file, %s", err)
  6. return false
  7. }
  8. var configuration config.ConfigSuper
  9. err := viper.Unmarshal(&configuration)
  10. if err != nil {
  11. log.Fatalf("unable to decode into struct, %v", err)
  12. }
  13. fmt.Printf("%+v\n", configuration)
英文:

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

  1. 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

  1. zones:
  2. - id: 1
  3. clusters:
  4. - cluster_id: 1
  5. k3s_config_file: "k3s-cluster-1-config.yaml"
  6. - cluster_id: 2
  7. k3s_config_file: "k3s-cluster-2-config.yaml"
  8. - cluster_id: 3
  9. k3s_config_file: "k3s-cluster-3-config.yaml"
  10. - id: 2
  11. clusters:
  12. - cluster_id: 1
  13. k3s_config_file: "k3s-cluster-1-config.yaml"
  14. - cluster_id: 2
  15. k3s_config_file: "k3s-cluster-2-config.yaml"
  16. - cluster_id: 3
  17. k3s_config_file: "k3s-cluster-3-config.yaml"

configuration.go

  1. package config
  2. type Zones struct {
  3. ClustersOuter map[string][]ClustersOuter `mapstructure:"zones"`
  4. Id int `mapstructure:"id"`
  5. }
  6. type ClustersInner struct {
  7. ClusterId int `mapstructure:"cluster_id"`
  8. K3sConfigFile string `mapstructure:"k3s_config_file"`
  9. }
  10. type ClustersOuter struct {
  11. ClustersInner map[string][]ClustersInner `mapstructure:"clusters"`
  12. }
  13. type ConfigSuper map[string][]Zones

main.go

  1. viper.SetConfigName("config")
  2. viper.AddConfigPath(".")
  3. viper.SetConfigType("yaml")
  4. if err := viper.ReadInConfig(); err != nil {
  5. log.Fatalf("Error reading config file, %s", err)
  6. return false
  7. }
  8. var configuration config.ConfigSuper
  9. err := viper.Unmarshal(&configuration)
  10. if err != nil {
  11. log.Fatalf("unable to decode into struct, %v", err)
  12. }
  13. fmt.Printf("%+v\n", configuration)

答案1

得分: 3

你的结构类型与YAML类型不匹配,看起来你将映射和切片组合在一起,而实际上你只处理切片。在YAML中,映射的格式如下:

  1. myMap:
  2. key1: value1

而数组的格式如下:

  1. myArray:
  2. - foo: bar

不幸的是,你的配置对象混乱到我无法理解意图,所以我为你重新编写了它。这些类型可以被Viper解码而没有任何问题。

  1. type Config struct {
  2. Zones []Zone `mapstructure:"zones"`
  3. }
  4. type Zone struct {
  5. ID int `mapstructure:"id"`
  6. Clusters []Cluster `mapstructure:"clusters"`
  7. }
  8. type Cluster struct {
  9. ClusterID int `mapstructure:"cluster_id"`
  10. K3sConfigFile string `mapstructure:"k3s_config_file"`
  11. }

Config 结构体是根对象,请确保解组到该结构体中。

  1. config := Config{}
  2. err = viper.Unmarshal(&config)
英文:

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:

  1. myMap:
  2. key1: value1

and arrays look like this:

  1. myArray:
  2. - 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.

  1. type Config struct {
  2. Zones []Zone `mapstructure:"zones"`
  3. }
  4. type Zone struct {
  5. ID int `mapstructure:"id"`
  6. Clusters []Cluster `mapstructure:"clusters"`
  7. }
  8. type Cluster struct {
  9. ClusterID int `mapstructure:"cluster_id"`
  10. K3sConfigFile string `mapstructure:"k3s_config_file"`
  11. }

The Config struct is the root object, make sure to unmarshal into that.

  1. config := Config{}
  2. err = viper.Unmarshal(&config)

huangapple
  • 本文由 发表于 2021年6月5日 04:55:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/67843868.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定