J'ai un objet JSON similaire à celui-ci:
{
"name": "Cain",
"parents": {
"mother" : "Eve",
"father" : "Adam"
}
}
Maintenant, je veux analyser "nom" et "mère" dans cette structure:
struct {
Name String
Mother String `json:"???"`
}
Je veux spécifier le nom du champ JSON avec le json:...
struct tag, mais je ne sais pas quoi utiliser comme balise, car ce n'est pas le premier objet qui m'intéresse. Je n'ai rien trouvé à ce sujet dans le encoding/json
package docs ni dans le blog populaire JSON et Go . J'ai également testé mother
, parents/mother
et parents.mother
.
Malheureusement, contrairement à encoding/xml
, le package json
ne permet pas d'accéder aux valeurs imbriquées. Vous voudrez soit créer une structure Parents distincte, soit attribuer le type à map[string]string
. Par exemple:
type Person struct {
Name string
Parents map[string]string
}
Vous pourriez alors fournir un getter pour la mère comme suit:
func (p *Person) Mother() string {
return p.Parents["mother"]
}
Cela peut ou non jouer dans votre base de code actuelle et si la refactorisation du champ Mother
en un appel de méthode n'est pas dans le menu, alors vous voudrez peut-être créer une méthode distincte pour le décodage et la conformité à votre structure actuelle.
Vous pouvez utiliser des structures tant que vos données entrantes ne sont pas trop dynamiques.
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)
}
Voici un code que j'ai préparé très rapidement dans le 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))
}
Il pourrait y avoir une meilleure façon. J'ai hâte de voir les autres réponses. :-)
Plus récemment, gjson prend en charge la sélection des propriétés JSON imbriquées.
name := gjson.Get(json, "name")
mother := gjson.Get(json, "parents.mother")
Que diriez-vous d'utiliser une structure intermédiaire comme celle suggérée ci-dessus pour l'analyse, puis de mettre les valeurs pertinentes dans votre structure "réelle"?
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)
}