我有一个 YAML 格式的配置文件,我试图通过 http API 调用将其输出为 JSON。我正在使用gopkg.in/yaml.v2
. Yaml 可以有非字符串键,这意味着 yaml 被解组为 map[interface{}]interface{},Go 的 JSON 编组器不支持这种方式。因此,我在解组之前转换为map[string]interface{}。但我仍然得到:json: unsupported type: 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)
}
Run Code Online (Sandbox Code Playgroud)
您的解决方案仅转换“顶层”级别的值。如果值也是映射(嵌套映射),您的解决方案不会转换它们。
此外,您只需“复制”带有键的值string
,其余的将被排除在结果映射之外。
这是一个递归转换嵌套映射的函数:
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
}
Run Code Online (Sandbox Code Playgroud)
测试它:
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))
Run Code Online (Sandbox Code Playgroud)
输出(在Go Playground上尝试):
{"1":"one","three":{"3.1":3.1},"two":2}
Run Code Online (Sandbox Code Playgroud)
需要注意的一些事项:
为了隐藏interface{}
密钥,我使用了fmt.Sprint()
可以处理所有类型的密钥。可以为已经是值的键switch
提供专用的情况,以避免调用。这只是出于性能原因,结果是一样的。string
string
fmt.Sprint()
上面的convert()
函数没有进入切片。因此,例如,如果映射包含一个切片 ( []interface{}
) 值,该切片也可能包含映射,则这些值将不会被转换。有关完整的解决方案,请参阅下面的库。
有一个库github.com/icza/dyno
对此有优化的内置支持(披露:我是作者)。使用dyno
,它看起来像这样:
var m map[interface{}]interface{} = ...
m2 := dyno.ConvertMapI2MapS(m)
Run Code Online (Sandbox Code Playgroud)
dyno.ConvertMapI2MapS()
也进入并转换[]interface{}
切片中的地图。
另请参阅可能的重复:Convert yaml to json without struct
归档时间: |
|
查看次数: |
6490 次 |
最近记录: |