2012-11-13 34 views
12

Miễn là tôi có cặp khóa-giá trị unmarshalling là khá thẳng về phía trước nhưng làm thế nào tôi sẽ unmarshall một mảng các loại khác nhau theo thứ tự khác nhau? Các yếu tố duy nhất được xác định rõ ràng và được biết đến nhưng thứ tự thì không.Làm thế nào để unmarshall một loạt các loại khác nhau một cách chính xác?

Tôi không thể đưa ra giải pháp đẹp.

Tôi có cố gắng và báo lỗi trên tất cả các yếu tố không? Có loại hình công đoàn nào có thể làm điều đó cho tôi không?

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

Trả lời

21

Tới blog chính thức có một bài viết thú vị về encoding/json: JSON and GO. Có thể "Giải mã dữ liệu tùy ý" thành giao diện {} và sử dụng xác nhận kiểu để xác định kiểu động.

Mã của bạn có thể được có thể được sửa đổi như sau:

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

Nó cung cấp cho đầu ra như sau:

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" 

Nó chưa đc hoàn thiện, nhưng cho thấy làm thế nào nó sẽ làm việc.

+0

Chính xác những gì tôi đang tìm kiếm. –

+1

Phần còn thiếu ở bên cạnh tôi là [loại xác nhận] (http://golang.org/ref/spec#Type_assertions) –

Các vấn đề liên quan