2012-11-13 12 views
12

Dopóki mam pary klucz-wartość, niemamostrzanie jest dość proste, ale w jaki sposób mogę rozpakować tablicę różnych typów w innej kolejności? Pojedyncze elementy są dobrze zdefiniowane i znane, ale kolejność nie jest.Jak poprawnie odfiltrować tablicę różnych typów?

Nie mogę wymyślić pięknego rozwiązania.

Czy próbowałbym pomyłek we wszystkich elementach? Czy jest jakiś rodzaj związku, który mógłby to dla mnie zrobić?

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

Odpowiedz

21

Idź oficjalny blog ma ładny artykuł o encoding/json: JSON and GO. Możliwe jest "Dekodowanie dowolnych danych" w interfejsie {} i użycie asercji typu w celu dynamicznego określenia typu.

Twój kod może być modyfikowany chyba do tego:

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

Daje wyjście następująco:

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" 

To nie jest jeszcze kompletna, ale pokazuje, jak to zadziała.

+0

Dokładnie tego, czego szukałem. –

+1

Brakującą częścią po mojej stronie było [typ potwierdzenia] (http://golang.org/ref/spec#Type_assertions) –

Powiązane problemy