2016-11-22 79 views
3
Services: 
- Orders: 
    - ID: $save ID1 
     SupplierOrderCode: $SupplierOrderCode 
    - ID: $save ID2 
     SupplierOrderCode: 111111 

我想這個YAML字符串轉換成JSON,導致源數據是動態的,所以我不能把它映射到一個結構:YAML轉換成JSON無結構(Golang)

var body interface{} 
err := yaml.Unmarshal([]byte(s), &body) 

然後我想該接口再次轉換成JSON字符串:

b, _ := json.Marshal(body) 

但出現錯誤:

panic: json: unsupported type: map[interface {}]interface {} 
+0

像這樣創建body var:'body:= make(map [string] interface {})' –

回答

11

前言:我對以下解決方案進行了優化和改進,並將其作爲庫發佈在此處:github.com/icza/dyno。以下convert()功能可用作dyno.ConvertMapI2MapS()


的問題是,如果你使用的最通用的interface{}類型解組,由github.com/go-yaml/yaml包使用的默認類型,以解組鍵值對將map[interface{}]interface{}

的第一個想法是使用map[string]interface{}

var body map[string]interface{} 

但這種嘗試達不到,如果YAML配置的深度超過一個,因爲這body地圖將包含更多的地圖,它的類型將再次map[interface{}]interface{}

問題是深度未知,並且可能有其他值不是地圖,所以使用map[string]map[string]interface{}並不好。

一個可行的辦法是讓yaml解組到interface{}類型的值,並辦理結果遞歸,並且將每個遇到map[interface{}]interface{}map[string]interface{}值。必須處理地圖和切片。

下面是該轉換器功能的例子:使用它

func convert(i interface{}) interface{} { 
    switch x := i.(type) { 
    case map[interface{}]interface{}: 
     m2 := map[string]interface{}{} 
     for k, v := range x { 
      m2[k.(string)] = convert(v) 
     } 
     return m2 
    case []interface{}: 
     for i, v := range x { 
      x[i] = convert(v) 
     } 
    } 
    return i 
} 

和:

func main() { 
    fmt.Printf("Input: %s\n", s) 
    var body interface{} 
    if err := yaml.Unmarshal([]byte(s), &body); err != nil { 
     panic(err) 
    } 

    body = convert(body) 

    if b, err := json.Marshal(body); err != nil { 
     panic(err) 
    } else { 
     fmt.Printf("Output: %s\n", b) 
    } 
} 

const s = `Services: 
- Orders: 
    - ID: $save ID1 
     SupplierOrderCode: $SupplierOrderCode 
    - ID: $save ID2 
     SupplierOrderCode: 111111 
` 

輸出:

Input: Services: 
- Orders: 
    - ID: $save ID1 
     SupplierOrderCode: $SupplierOrderCode 
    - ID: $save ID2 
     SupplierOrderCode: 111111 

Output: {"Services":[{"Orders":[ 
    {"ID":"$save ID1","SupplierOrderCode":"$SupplierOrderCode"}, 
    {"ID":"$save ID2","SupplierOrderCode":111111}]}]} 

有一點要注意:從YAML切換到JSON通過Go地圖,您將失去項目的順序,因爲Go地圖中的元素(鍵值對)沒有排序。這可能是也可能不是問題。

+0

非常感謝Icza,你真好:D – huynhminhtuan

0

https://github.com/ghodss/yaml是「圍繞go-yaml設計的封裝器,它可以在封送到結構體和從結構體封送時更好地處理YAML」。除其他外,它提供了yaml.YAMLToJSON方法,應該做你想做的。