使用接口动态映射YAML的更简便方法是什么?

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

More easy way of using Interfaces to map YAML dynamically?

问题

我正在尝试动态解析一个YAML文件(因此没有结构体)。

package main

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

func main() {	
	var out = `
a: First!
f: Second
b:
  c: 
    f: Third
`
	m := make(map[interface{}]interface{})
	err := yaml.Unmarshal([]byte(out), &m)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(m["b"].(map[interface{}]interface{})["c"].(map[interface{}]interface{})["f"])
}

每次我需要访问一个子键时,我被迫将相关的map变量转换为(map[interface{}]interface{})。这对我来说有点麻烦,因为我必须遍历整个map。

在Go中,有没有更简单的方法来解析YAML文件?

英文:

I am trying to parse a yaml file dynamically (Therefore no struct).

package main

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

func main() {	
	var out = `
a: First!
f: Second
b:
  c: 
    f: Third
`
	m := make(map[interface{}]interface{})
	err := yaml.Unmarshal([]byte(out), &m)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(m["b"].(map[interface{}]interface{})["c"].(map[interface{}]interface{})["f"])
}

Everytime I have to access a subkey, I am forced to convert map variable in question to (map[interface{}]interface{}). This is causing bit of a hassle for me as I have to iterate through the map.

Is there any easier method for parsing YAML file in Go?

答案1

得分: 1

另一种方法是将yaml数据结构展平为键值对映射,其中键和值都是字符串。然后,如果你需要实际的类型(例如5是一个整数),你可以自己进行转换。示例代码如下:

func main() {
    any := map[string]interface{}{}
    err := yaml.Unmarshal([]byte(out), &any)
    if err != nil {
        log.Fatal(err)
    }

    flatmap := map[string]string{}
    for k, v := range any {
        flatten(k, v, flatmap)
    }

    for k, v := range flatmap {
        fmt.Println(k, "=", v)
    }
}

func flatten(prefix string, value interface{}, flatmap map[string]string) {
    submap, ok := value.(map[interface{}]interface{})
    if ok {
        for k, v := range submap {
            flatten(prefix+"."+k.(string), v, flatmap)
        }
        return
    }
    stringlist, ok := value.([]interface{})
    if ok {
        flatten(fmt.Sprintf("%s.size", prefix), len(stringlist), flatmap)
        for i, v := range stringlist {
            flatten(fmt.Sprintf("%s.%d", prefix, i), v, flatmap)
        }
        return
    }
    flatmap[prefix] = fmt.Sprintf("%v", value)
}

这段代码将yaml数据结构展平为键值对的形式,并打印出展平后的结果。你可以根据需要进行修改和使用。

英文:

Another approach is to flatten the yaml data structure into a key,value map in which keys and values are strings. Then if you need the actual type (5 being an int) you can do the conversion yourself. Example:

"a" = "First!"
"f" = "Second"
"b.c.f" = "Third"
"b.c.g.size" = "2"
"b.c.g.0 = "zero"
"b.c.g.1 = "one" 

In Go:

func main() {
	any := map[string]interface{}{}
	err := yaml.Unmarshal([]byte(out), &any)
	if err != nil {
		log.Fatal(err)
	}

	flatmap := map[string]string{}
	for k, v := range any {
		flatten(k, v, flatmap)
	}

	for k, v := range flatmap {
		fmt.Println(k, "=", v)
	}
}

func flatten(prefix string, value interface{}, flatmap map[string]string) {
	submap, ok := value.(map[interface{}]interface{})
	if ok {
		for k, v := range submap {
			flatten(prefix+"."+k.(string), v, flatmap)
		}
		return
	}
	stringlist, ok := value.([]interface{})
	if ok {
		flatten(fmt.Sprintf("%s.size", prefix), len(stringlist), flatmap)
		for i, v := range stringlist {
			flatten(fmt.Sprintf("%s.%d", prefix, i), v, flatmap)
		}
		return
	}
	flatmap[prefix] = fmt.Sprintf("%v", value)
}

huangapple
  • 本文由 发表于 2014年12月1日 19:12:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/27227129.html
匿名

发表评论

匿名网友

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

确定