将嵌套的配置YAML映射到结构体

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

Mapping Nested Config Yaml to struct

问题

我是你的中文翻译助手,以下是翻译好的内容:

我刚开始学习Go语言,并且正在使用viper加载所有的配置。我目前有一个YAML文件,内容如下:

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

需要注意的是,countrycode是动态的,可以随时添加到任何国家。那么我该如何将其映射到一个结构体中,以便我可以按如下方式进行操作:

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

我尝试通过循环来构建它,但是我在这里卡住了:

for country, queries := range viper.GetStringMap("countryQueries") {
    // 我似乎无法对queries进行任何操作,我希望能够循环遍历它
    for _, query := range queries {} // 这里报错
}

希望对你有帮助!

英文:

I'm new to go, and I'm 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
}

答案1

得分: 8

在阅读了一些资料后,我发现 viper 有自己的反序列化功能,非常好用。你可以在这里找到更多信息:https://github.com/spf13/viper#unmarshaling

这是我所做的:

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))
    }
}

希望对你有帮助!

英文:

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

得分: 1

这是一段使用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)
}
英文:

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

得分: 1

如果你想将你的yaml结构映射到一个严格的Go语言struct,你可以使用mapstructure库来映射每个国家下的嵌套键值对。

例如:

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)
	}
}
英文:

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

得分: 0

你可以使用这个包 https://github.com/go-yaml/yaml 在Go语言中进行YAML的序列化和反序列化。

英文:

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

huangapple
  • 本文由 发表于 2017年1月13日 17:14:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/41631008.html
匿名

发表评论

匿名网友

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

确定