2012-11-13 66 views
12

只要我有鍵值對解組是非常直接的,但我將如何以不同的順序解組一個不同類型的數組?單個元素是明確定義和已知的,但順序不是。如何正確解組一個不同類型的數組?

我不能想出一個美麗的解決方案。

我會嘗試和錯誤的所有元素? 是否有某種可以爲我做的工會類型?

playground version

package main 

import (
    "encoding/json" 
    "fmt" 
) 

var my_json string = `{ 
    "an_array":[ 
     "with_a string", 
     { 
      "and":"some_more", 
      "different":["nested", "types"] 
     } 
    ] 
}` 

type MyInner struct { 
    And  string 
    Different []string 
} 

type MyJSON struct { 
    An_array []json.RawMessage 
} 

func main() { 
    var my_json_test MyJSON 

    e := json.Unmarshal([]byte(my_json), &my_json_test) 
    if e != nil { 
     fmt.Println(e) 
    } else { 
     for index, value := range my_json_test.An_array { 
      fmt.Println("index: ", index) 
      fmt.Println("value: ", string(value)) 
     } 
     var my_inner MyInner 
     err := json.Unmarshal(my_json_test.An_array[1], &my_inner) 
     if err != nil { 
      fmt.Println(err) 
     } else { 
      fmt.Println("inner structure: ", my_inner) 
     } 
    } 
} 

回答

21

去官方博客上的一篇好文約encoding/jsonJSON and GO。可以將「任意數據解碼」到一個接口中,並使用類型斷言來動態確定類型。

你的代碼可以可能被修改到這一點:

package main 

import (
    "encoding/json" 
    "fmt" 
) 

var my_json string = `{ 
    "an_array":[ 
    "with_a string", 
    { 
     "and":"some_more", 
     "different":["nested", "types"] 
    } 
    ] 
}` 

func WTHisThisJSON(f interface{}) { 
    switch vf := f.(type) { 
    case map[string]interface{}: 
     fmt.Println("is a map:") 
     for k, v := range vf { 
      switch vv := v.(type) { 
      case string: 
       fmt.Printf("%v: is string - %q\n", k, vv) 
      case int: 
       fmt.Printf("%v: is int - %q\n", k, vv) 
      default: 
       fmt.Printf("%v: ", k) 
       WTHisThisJSON(v) 
      } 

     } 
    case []interface{}: 
     fmt.Println("is an array:") 
     for k, v := range vf { 
      switch vv := v.(type) { 
      case string: 
       fmt.Printf("%v: is string - %q\n", k, vv) 
      case int: 
       fmt.Printf("%v: is int - %q\n", k, vv) 
      default: 
       fmt.Printf("%v: ", k) 
       WTHisThisJSON(v) 
      } 

     } 
    } 
} 

func main() { 

    fmt.Println("JSON:\n", my_json, "\n") 

    var f interface{} 
    err := json.Unmarshal([]byte(my_json), &f) 
    if err != nil { 
     fmt.Println(err) 
    } else { 
     fmt.Printf("JSON: ") 
     WTHisThisJSON(f) 
    } 
} 

它給輸出如下:

JSON: 
{ 
    "an_array":[ 
    "with_a string", 
    { 
     "and":"some_more", 
     "different":["nested", "types"] 
    } 
    ] 
} 

JSON: is a map: 
an_array: is an array: 
0: is string - "with_a string" 
1: is a map: 
and: is string - "some_more" 
different: is an array: 
0: is string - "nested" 
1: is string - "types" 

它尚未完成,但顯示了它是如何要去工作。

+0

正是我在找的東西。 –

+1

我身邊缺失的部分是[type assertion](http://golang.org/ref/spec#Type_assertions) –