Mapping Nested Config Yaml to struct

北城余情 提交于 2019-12-11 01:45:30

问题


Im new to go, and im using viper do load all my config what currently i have is the YAML look like below

 countryQueries:
  sg:
    - qtype: gmap
      qplacetype: postal_code
    - qtype: gmap
      qplacetype: address
    - qtype: geocode
      qplacetype: street_address

  hk:
    - qtype: gmap
      qplacetype: postal_code
    - qtype: gmap
      qplacetype: address
    - qtype: geocode
      qplacetype: street_address

to note that the countrycode are dynamic it could be added anytime for any countries. So how do i map this to a struct where technically speaking i can do

for _, query := range countryQueries["sg"] { }

i try to contruct it myself by looping it but im stucked here

for country, queries := range viper.GetStringMap("countryQueries") {
    // i cant seem to do anything with queries, which i wish to loop it
    for _,query := range queries {} //here error
}

Any help will be much appreciated


回答1:


After done some reading realized that viper has it own unmarshaling capabilities which works great https://github.com/spf13/viper#unmarshaling

So here what i did

type Configuration struct {
    Countries map[string][]CountryQuery `mapstructure:"countryQueries"`
}

type CountryQuery struct {
    QType      string
    QPlaceType string
}

func BuildConfig() {
    viper.SetConfigName("configFileName")
    viper.AddConfigPath("./config")
    err := viper.ReadInConfig()
    if err != nil {
        panic(fmt.Errorf("Error config file: %s \n", err))
    }

    var config Configuration

    err = viper.Unmarshal(&config)
    if err != nil {
        panic(fmt.Errorf("Unable to decode Config: %s \n", err))
    }
}



回答2:


Here some simple code with go-yaml:

package main

import (
    "fmt"
    "gopkg.in/yaml.v2"
    "log"
)

var data = `
countryQueries:
  sg:
    - qtype: gmap
      qplacetype: postal_code
    - qtype: gmap
      qplacetype: address
    - qtype: geocode
      qplacetype: street_address

  hk:
    - qtype: gmap
      qplacetype: postal_code
    - qtype: gmap
      qplacetype: address
    - qtype: geocode
      qplacetype: street_address
`

func main() {
    m := make(map[interface{}]interface{})

    err := yaml.Unmarshal([]byte(data), &m)
    if err != nil {
        log.Fatalf("error: %v", err)
    }

    fmt.Printf("%v\n", m)
}



回答3:


If you're looking to map your yaml structure to a strict golang struct you could make use of the mapstructure library to map the nested key/value pairs under each country.

For example:

package main

import (
    "github.com/spf13/viper"
    "github.com/mitchellh/mapstructure"
    "fmt"
    "log"
)

type CountryConfig struct {
    Qtype string
    Qplacetype string
}
type QueryConfig struct {
    CountryQueries map[string][]CountryConfig;
}
func NewQueryConfig () QueryConfig {
    queryConfig := QueryConfig{}
    queryConfig.CountryQueries = map[string][]CountryConfig{}
    return queryConfig
}
func main() {

    viper.SetConfigName("test")
    viper.AddConfigPath(".")
    err := viper.ReadInConfig()
    queryConfig := NewQueryConfig()
    if err != nil {
        log.Panic("error:", err)
    } else {
        mapstructure.Decode(viper.AllSettings(), &queryConfig)
    }
    for _, config := range queryConfig.CountryQueries["sg"] {

        fmt.Println("qtype:", config.Qtype, "qplacetype:", config.Qplacetype)
    }
}



回答4:


You can use this package https://github.com/go-yaml/yaml to serialize/deserialize YAML in Go.



来源:https://stackoverflow.com/questions/41631008/mapping-nested-config-yaml-to-struct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!