2012-11-27 13 views
35

Mam obiektu JSON podobny do tego:Jak przeanalizować wewnętrzne pole w zagnieżdżonym obiekcie JSON w Golang?

{ 
    "name": "Cain", 
    "parents": { 
    "mother" : "Eve", 
    "father" : "Adam" 
    } 
} 

Teraz chcę analizować „nazwa” i „matka” w tej struktury:

struct { 
    Name String 
    Mother String `json:"???"` 
} 

chcę podać nazwę pola JSON ze znacznikiem struct json:..., ale nie wiem, co używać jako znacznika, ponieważ nie jest to obiekt główny, który mnie interesuje. Nie znalazłem nic na ten temat w dokumentach pakietu encoding/json ani w popularnym wpisie na blogu JSON and Go. Przetestowałem także: mother, parents/mother i parents.mother.

Odpowiedz

16

Niestety, w przeciwieństwie do encoding/xml pakiet json nie zapewnia sposób dostępu do wartości zagnieżdżonych. Będziesz chciał utworzyć osobną strukturę Parents lub przypisać typ do map[string]string. Na przykład:

type Person struct { 
    Name string 
    Parents map[string]string 
} 

Można następnie dostarczyć getter dla matki jako tak:

func (p *Person) Mother() string { 
    return p.Parents["mother"] 
} 

To może lub nie może grać w aktualnym kodzie i jeśli refactoring pole Mother do wywołania metody nie jest w menu możesz utworzyć osobną metodę dekodowania i dostosowywania do aktualnej struktury.

6

Oto niektóre kodu upiekłam się bardzo szybko w Go Playground

http://play.golang.org/p/PiWwpUbBqt

package main 

import (
    "fmt" 
    "encoding/json" 
    ) 

func main() { 
    encoded := `{ 
     "name": "Cain", 
     "parents": { 
      "mother": "Eve" 
      "father": "Adam" 
     } 
    }` 

    // Decode the json object 
    var j map[string]interface{} 
    err := json.Unmarshal([]byte(encoded), &j) 
    if err != nil { 
     panic(err) 
    } 

    // pull out the parents object 
    parents := j["parents"].(map[string]interface{}) 

    // Print out mother and father 
    fmt.Printf("Mother: %s\n", parents["mother"].(string)) 
    fmt.Printf("Father: %s\n", parents["father"].(string)) 
} 

Nie może być lepszy sposób. Czekam z niecierpliwością na inne odpowiedzi. :-)

+0

Wiem, że to działa, ale mam nadzieję, że istnieje bardziej ... czytelne rozwiązanie. – keks

+0

Musi działać w ten sposób, ponieważ interfejs {} musi być uznany za typ (w tym przypadku wpisz map [string] interface {}). Prostszym sposobem jest użycie biblioteki lib z metodami pomocniczymi, takimi jak [go-simplejson] (http://godoc.org/github.com/bitly/go-simplejson) – Druska

+0

to unmarshalling zagnieżdżonej struktury daje mi poważne bóle głowy. boooo –

17

Można używać struktur, o ile dane przychodzące nie są zbyt dynamiczne.

http://play.golang.org/p/bUZ8l6WgvL

package main 

import (
    "fmt" 
    "encoding/json" 
    ) 

type User struct { 
    Name string 
    Parents struct { 
     Mother string 
     Father string 
    } 
} 

func main() { 
    encoded := `{ 
     "name": "Cain", 
     "parents": { 
      "mother": "Eve", 
      "father": "Adam" 
     } 
    }` 

    // Decode the json object 
    u := &User{} 
    err := json.Unmarshal([]byte(encoded), &u) 
    if err != nil { 
     panic(err) 
    } 

    // Print out mother and father 
    fmt.Printf("Mother: %s\n", u.Parents.Mother) 
    fmt.Printf("Father: %s\n", u.Parents.Father) 
} 
+1

Jestem tego również świadomy. Jednak nie chcę używać dwóch struktur, ale jednej i nie chcę ich zagnieżdżać. Tagi pól strukturalnych pozwalają określić, które pole JSON powinno zostać użyte, ale byłem ciekawy, czy dają one sposób na dostęp do zagnieżdżonych pól, pól, które nie są członami obiektu root. – keks

+1

'remy_o' powiedział na' # go-nuts', że pakiet 'encoding/json' nie robi tego, o co prosiłem, więc jest to odpowiedź, z którą utknąłem. Lub w jego słowach: "pakiet json nie jest XPath". – keks

2

Co powiesz na użycie struktury pośredniczącej, takiej jak sugerowana powyżej do analizy, a następnie umieszczenie odpowiednich wartości w "prawdziwej" strukturze?

import (
    "fmt" 
    "encoding/json" 
    ) 

type MyObject struct{ 
    Name string 
    Mother string 
} 

type MyParseObj struct{ 
    Name string 
    Parents struct { 
     Mother string 
     Father string 
    } 
} 


func main() { 
    encoded := `{ 
     "name": "Cain", 
     "parents": { 
      "mother": "Eve", 
      "father": "Adam" 
     } 
    }` 

    pj := &MyParseObj{} 
    if err := json.Unmarshal([]byte(encoded), pj); err != nil { 
     return 
    } 
    final := &MyObject{Name: pj.Name, Mother: pj.Parents.Mother} 
    fmt.Println(final) 
} 
3

Niedawno gjson obsługuje wybór zagnieżdżonych właściwości JSON.

name := gjson.Get(json, "name") 
mother := gjson.Get(json, "parents.mother") 
Powiązane problemy