yamlファイルでネストされた検索を実行する必要があったのと同様の要件がありました。私が箱の解決策を見つけなかったので、私はそれを自分で書く必要がありました。
私はまたしたくなかった私は、この構造体からネストされた値にアクセスし、印刷したいと出力のような
--- yaml->a: Easy!
--- yaml->b->c: 2
--- yaml->b->x: None //not existing in the yaml
--- yaml->y->w: None //not existing in the yaml
--- yaml->b->d[0]: 3 //accessing value from a list
--- yaml->e->f->g: hi
以下でなければならない
"a": "Easy!"
"b":
"c": "2"
"d": ["3", "4"]
"e":
"f": {"g":"hi","h":"6"}
以下のような内容を持つYAMLファイルを持っています解析されたyamlを保持する構造体を定義します。 golangの最も一般的な構造はinterface {}です。 yamlをアンマーシャリングするのに最適な構造はmap[interface{}]interface{}
です。 Javaから来る人々の場合、これはMap<Object,Object>
に似ています。データがアンマーシャリングされると、ネストされたキーを使用して構造体を走査し、値を返す関数を記述する必要がありました。
以下はそのコードです。コメントをオンにして、コードがネストされた構造をどのようにトラバースし、最後に値を取得するかを知るために実行します。この例では、yamlのすべての値が文字列であると仮定していますが、これは数値のキーと値に対しても拡張できます。
package main
import (
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"reflect"
)
func main() {
testFile := "test.yaml"
testYaml, rerr := ioutil.ReadFile(testFile)
if rerr != nil {
fmt.Errorf("error reading yaml file: %v", rerr)
}
m := make(map[interface{}]interface{})
if uerr := yaml.Unmarshal([]byte(testYaml), &m); uerr != nil {
fmt.Errorf("error parsing yaml file: %v", uerr)
}
fmt.Printf("--- yaml->a: %v\n\n", getValue(m, []string{"a"}, -1)) //single value in a map
fmt.Printf("--- yaml->b->c: %v\n\n", getValue(m, []string{"b", "c"}, -1)) //single value in a nested map
fmt.Printf("--- yaml->b->x: %v\n\n", getValue(m, []string{"b", "x"}, -1)) //value for a non existent nest key
fmt.Printf("--- yaml->y->w: %v\n\n", getValue(m, []string{"y", "w"}, -1)) //value for a non existent nest key
fmt.Printf("--- yaml->b->d[0]: %v\n\n", getValue(m, []string{"b", "d"}, 0))
fmt.Printf("--- yaml->e->f->g: %v\n\n", getValue(m, []string{"e", "f", "g"}, -1))
}
func getValue(obj map[interface{}]interface{}, keys []string, indexOfElementInArray int) string {
//fmt.Printf("--- Root object:\n%v\n\n", obj)
value := "None"
queryObj := obj
for i := range keys {
if queryObj == nil {
break
}
if i == len(keys)-1 {
break
}
key := keys[i]
//fmt.Printf("--- querying for sub object keyed by %v\n", key)
if queryObj[key] != nil {
queryObj = queryObj[key].(map[interface{}]interface{})
//fmt.Printf("--- Sub object keyed by %v :\n%v\n\n", key, queryObj)
} else {
//fmt.Printf("--- No sub object keyed by %v :\n%v\n\n", key)
break
}
}
if queryObj != nil {
lastKey := keys[len(keys)-1]
//fmt.Printf("--- querying for value keyed by %v\n", lastKey)
if queryObj[lastKey] != nil {
objType := reflect.TypeOf(queryObj[lastKey])
//fmt.Printf("Type of value %v\n", objType)
if objType.String() == "[]interface {}" {
//fmt.Printf("Object is a array %v\n", objType)
tempArr := queryObj[lastKey].([]interface{})
//fmt.Printf("Length of array is %v\n", len(tempArr))
if indexOfElementInArray >= 0 && indexOfElementInArray < len(tempArr) {
value = queryObj[lastKey].([]interface{})[indexOfElementInArray].(string)
}
} else {
value = queryObj[lastKey].(string)
}
}
}
return value
}