在Go中将YAML转换为JSON
我有一个YAML格式的配置文件,我正试图通过http API调用将其输出为JSON。我正在使用在Go中将YAML转换为JSON,json,go,yaml,Json,Go,Yaml,我有一个YAML格式的配置文件,我正试图通过http API调用将其输出为JSON。我正在使用gopkg.in/yaml.v2解组。Yaml可以有非字符串键,这意味着Yaml被解组为map[interface{}]interface{},Go的JSON封送器不支持这一点。因此,在解组之前,我将转换为map[string]接口{}。但是我仍然得到:json:unsupported类型:map[interface{}]interface{}。我不明白。变量cfy不是map[interface{}]i
gopkg.in/yaml.v2
解组。Yaml可以有非字符串键,这意味着Yaml被解组为map[interface{}]interface{},Go的JSON封送器不支持这一点。因此,在解组之前,我将转换为map[string]接口{}。但是我仍然得到:json:unsupported类型:map[interface{}]interface{}
。我不明白。变量cfy
不是map[interface{}]interface{}
import (
"io/ioutil"
"net/http"
"encoding/json"
"gopkg.in/yaml.v2"
)
func GetConfig(w http.ResponseWriter, r *http.Request) {
cfy := make(map[interface{}]interface{})
f, err := ioutil.ReadFile("config/config.yml")
if err != nil {
// error handling
}
if err := yaml.Unmarshal(f, &cfy); err != nil {
// error handling
}
//convert to a type that json.Marshall can digest
cfj := make(map[string]interface{})
for key, value := range cfy {
switch key := key.(type) {
case string:
cfj[key] = value
}
}
j, err := json.Marshal(cfj)
if err != nil {
// errr handling. We get: "json: unsupported type: map[interface {}]interface" {}
}
w.Header().Set("content-type", "application/json")
w.Write(j)
}
您的解决方案仅转换“顶部”级别的值。如果值也是映射(嵌套映射),则您的解决方案不会转换这些值 此外,您仅使用
字符串键“复制”值,其余值将从结果映射中删除
下面是一个递归转换嵌套映射的函数:
func convert(m map[interface{}]interface{}) map[string]interface{} {
res := map[string]interface{}{}
for k, v := range m {
switch v2 := v.(type) {
case map[interface{}]interface{}:
res[fmt.Sprint(k)] = convert(v2)
default:
res[fmt.Sprint(k)] = v
}
}
return res
}
测试它:
m := map[interface{}]interface{}{
1: "one",
"two": 2,
"three": map[interface{}]interface{}{
"3.1": 3.1,
},
}
m2 := convert(m)
data, err := json.Marshal(m2)
if err != nil {
panic(err)
}
fmt.Println(string(data))
输出(在上尝试):
需要注意的事项:
- 为了转换
接口{}
键,我使用了fmt.Sprint()
来处理所有类型。对于已经是string
值的键,开关可以有一个专用的string
大小写,以避免调用fmt.Sprint()
。这完全是出于性能原因,结果将是相同的
- 上面的
convert()
函数不分片。因此,例如,如果映射包含一个值,该值是一个切片([]接口{}
),该切片也可能包含映射,则这些值不会被转换。有关完整解决方案,请参阅下面的库
- 有一个库对此具有优化的内置支持(披露:我是作者)。使用
dyno
,它看起来是这样的:
var m map[interface{}]interface{} = ...
m2 := dyno.ConvertMapI2MapS(m)
也进入并转换[]接口{}
切片中的映射
另请参见可能的重复:发生错误的原因是您没有递归地进行转换,即值
可能仍然是一个映射[interface{}]interface{}。有一个你可能会觉得有用的。完全正确。我刚刚在测试中看到了。你想回答这个问题吗?谢谢。是的,我自己看到了,并开始编写你提供的函数。然后Peter(见注释)将我链接到一个提供yaml到json函数的包,所以我最终使用了它,但将此标记为答案。
var m map[interface{}]interface{} = ...
m2 := dyno.ConvertMapI2MapS(m)