簡體   English   中英

如何使用 Viper 從嵌套的 YAML 結構中獲取值?

[英]How do I use Viper to get a value from a nested YAML structure?

我的問題:

如何編寫下面的代碼以從嵌套的 yaml 結構中獲取字符串?

這是我的 yaml:

    element:
      - one:
          url: http://test
          nested: 123
      - two:
          url: http://test
          nested: 123

    weather:
      - test:
          zipcode: 12345
      - ca:
          zipcode: 90210

這是示例代碼

    viper.SetConfigName("main_config")
      viper.AddConfigPath(".")
      err := viper.ReadInConfig()
      if err != nil {
        panic(err)
      }
    testvar := viper.GetString("element.one.url")

我的問題:

當我打印這個時,我得到一個空字符串。 根據文檔,這是獲得嵌套元素的方式。 我懷疑它不起作用,因為元素是列表。 我需要做一個結構嗎? 我是新手,所以不確定如何制作一個,特別是如果它需要嵌套。

viper 庫中有不同的 Get 方法可用,並且您的 YML 結構類型為[]map[string]string ,因此要解析您的 YML 配置文件,您必須使用viper.Get方法。 所以你必須像這樣解析你的文件..

注意:您也可以使用 struct 來解組數據。 請參考這篇文章mapping-nested-config-yaml-to-struct

package main

import (
    "fmt"

    "github.com/spf13/viper"
)

func main() {
    viper.SetConfigName("config")
    viper.AddConfigPath(".")
    err := viper.ReadInConfig()
    if err != nil {
        panic(err)
    }
    testvar := viper.Get("element")
    fmt.Println(testvar)
    elementsMap := testvar.([]interface{})
    for k, vmap := range elementsMap {
        fmt.Print("Key: ", k) 
        fmt.Println(" Value: ", vmap)
        eachElementsMap := vmap.(map[interface{}]interface{})

        for k, vEachValMap := range eachElementsMap {
            fmt.Printf("%v: %v \n", k, vEachValMap)
            vEachValDataMap := vEachValMap.(map[interface{}]interface{})

            for k, v := range vEachValDataMap {
                fmt.Printf("%v: %v \n", k, v)
            }
        }
    }
}

// Output:
/*
Key: 0 Value:  map[one:map[url:http://test nested:123]]
one: map[url:http://test nested:123]
url: http://test
nested: 123
Key: 1 Value:  map[two:map[url:http://test nested:123]]
two: map[url:http://test nested:123]
url: http://test
nested: 123
*/

您可以使用UnmarshalUnmarshalKey解析全部或部分數據並填充結構。 它與解組 json 非常相似。

在您的情況下,代碼將如下所示:

package main

import (
    "fmt"
    "github.com/spf13/viper"
)

// here we define schema of data, just like what we might do when we parse json
type Element struct {
    Url    string `mapstructure:"url"`
    Nested int    `mapstructure:"nested"`
}

func main() {
    viper.SetConfigName("config")
    viper.AddConfigPath(".")
    err := viper.ReadInConfig()
    if err != nil {
        panic(err)
    }
    
    // data in `element` key is a map of string to Element. We define a variable to store data into it.
    elementParsed := make(map[string]*Element)
    // read the key `element` in the yaml file, and parse it's data and put it in `elementParsed` variable
    err = viper.UnmarshalKey("element", &elementParsed)
    if err != nil {
        panic(err)
    }

    fmt.Println(elementParsed["one"].Url) // will print: http://test 
    fmt.Println(elementParsed["one"].Nested) // will print: 123
}

您可以解組嵌套的配置文件。

main.go

package main

import (
    "fmt"
    "github.com/spf13/viper"
)

type NestedURL struct {
    URL string `mapstructure:"url"`
    Nested int `mapstructure:"nested"`
}

type ZipCode struct {
    Zipcode string `mapstructure:"zipcode"`
}

type Config struct {
    Element [] map[string]NestedURL `mapstructure:"element"`
    Weather [] map[string]ZipCode `mapstructure:"weather"`
}

func main() {
    viper.SetConfigName("config")
    viper.AddConfigPath(".")
    if err := viper.ReadInConfig();  err != nil {
        return
    }
    var config Config
    if err := viper.Unmarshal(&config); err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(config)
}

配置文件

element:
  - one:
      url: http://test
      nested: 123
  - two:
      url: http://test
      nested: 123
weather:
  - test:
      zipcode: 12345
  - ca:
      zipcode: 90210

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM