简体   繁体   English

在Go中将YAML转换为JSON

[英]Converting YAML to JSON in Go

I have a config file in YAML format, which I am trying to output as JSON via an http API call. 我有一个YAML格式的配置文件,我正在尝试通过http API调用将其输出为JSON。 I am unmarshalling using gopkg.in/yaml.v2 . 我正在使用gopkg.in/yaml.v2进行gopkg.in/yaml.v2 Yaml can have non-string keys, which means that the yaml is unmarshalled as map[interface{}]interface{}, which is not supported by Go's JSON marshaller. Yaml可以具有非字符串键,这意味着yaml被解编为map [interface {}] interface {},而Go的JSON marshaller不支持。 Therefore I convert to map[string]interface{} before unmarshalling. 因此,在解组之前,我将转换为map [string] interface {}。 But I still get: json: unsupported type: map[interface {}]interface" {} . I don't understand. The variable cfy is not map[interface{}]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)
}

Your solution only converts values at the "top" level. 您的解决方案仅转换“最高”级别的值。 If a value is also a map (nested map), your solution does not convert those. 如果值也是地图(嵌套地图),则您的解决方案不会将其转换。

Also you only "copy" the values with string keys, the rest will be left out of the result map. 同样,您仅使用string键“复制”值,其余的将不包含在结果图中。

Here's a function that recursively converts nested maps: 这是一个递归转换嵌套地图的函数:

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
}

Testing it: 测试它:

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))

Output (try it on the Go Playground ): 输出(在Go Playground上尝试):

{"1":"one","three":{"3.1":3.1},"two":2}

Some things to note: 注意事项:

  • To covert interface{} keys, I used fmt.Sprint() which will handle all types. 为了隐蔽interface{}键,我使用了fmt.Sprint()来处理所有类型。 The switch could have a dedicated string case for keys that are already string values to avoid calling fmt.Sprint() . switch可能具有专用的string大小写,用于已为string值的键,以避免调用fmt.Sprint() This is solely for performance reasons, the result will be the same. 这仅仅是出于性能方面的考虑,其结果将是相同的。

  • The above convert() function does not go into slices. 上面的convert()函数不会切成薄片。 So for example if the map contains a value which is a slice ( []interface{} ) which may also contain maps, those will not be converted. 因此,例如,如果映射包含一个值为切片( []interface{} )的值,该值也可能包含映射,则将不会转换这些值。 For a full solution, see the lib below. 有关完整的解决方案,请参见下面的库。

  • There is a lib github.com/icza/dyno which has an optimized, built-in support for this (disclosure: I'm the author). 有一个github.com/icza/dyno ,它对此具有优化的内置支持(公开:我是作者)。 Using dyno , this is how it would look like: 使用dyno ,结果如下所示:

     var m map[interface{}]interface{} = ... m2 := dyno.ConvertMapI2MapS(m) 

    dyno.ConvertMapI2MapS() also goes into and converts maps in []interface{} slices. dyno.ConvertMapI2MapS()也进入并转换[]interface{}切片中的地图。

Also see possible duplicate: Convert yaml to json without struct 另请参阅可能的重复项: 将yaml转换为不带struct的json

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM