J'analyse un fichier JSON avec une structure inhabituelle qui ressemble à ceci:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type id struct {
recordid string
record []record
}
type record struct {
name string
number uint32
dob string
email string
}
func main() {
jsonFile, err := os.Open("/home/emyrw/development/go/src/json_processor/demo.json")
if err != nil {
fmt.Println(err)
} else {
var records id
byteValue, _ := ioutil.ReadAll(jsonFile)
json.Unmarshal(byteValue, &records)
fmt.Println(records)
fmt.Println("opened demo.json")
defer jsonFile.Close()
}
}
J'ai travaillé sur des démos de code, mais j'aimerais tout mettre dans une structure, que je prévois ensuite de rechercher par la chaîne numérique qui est le nom de l'objet que je devinerais?
Je ne suis pas fort sur JSON ou Go, et c'est le code que j'ai écrit jusqu'à présent :
{
"394885":
{
"record":
{
"student_name": "Daryl Jones",
"student_number": 123884,
"student_dob": "12/10/1982",
"student_email": "djones@school.ac.uk",
}
},
}
Je ne suis pas sûr d'avoir bien compris, mais j'apprécierais tous les trucs ou conseils que quelqu'un a à offrir. J'ai cherché sur Google, mais aucun des échantillons que je trouve ne correspond tout à fait à mon scénario.
4 Réponses :
Vous pouvez utiliser cette structure pour votre type d'identifiant
var records map[string]id
Modifier
voici la solution de travail avec quelques explications: p >
puisque vous avez un json à plusieurs niveaux, vous pouvez l'analyser en structures imbriquées.
{
"394885":
{
"record":
{
"student_name": "Daryl Jones",
"student_number": 123884,
"student_dob": "12/10/1982",
"student_email": "djones@school.ac.uk"
}
}
}
pour analyser cette partie du json, vous avez besoin de cette structure
type id struct {
Record record
}
les champs doivent être exportés (commencer par une majuscule) et avoir une balise json qui correspond aux propriétés json.
{
"record":
{
"student_name": "Daryl Jones",
"student_number": 123884,
"student_dob": "12/10/1982",
"student_email": "djones@school.ac.uk"
}
}
pour cela partie pour fonctionner, vous avez besoin d'une structure imbriquée comme celle-ci
type record struct {
Name string `json:"student_name"`
Number uint32 `json:"student_number"`
Dob string `json:"student_dob"`
Email string `json:"student_email"`
}
le nom de fichier est à nouveau exporté mais comme il correspond à votre propriété json, vous n'avez pas besoin de la balise.
{
"student_name": "Daryl Jones",
"student_number": 123884,
"student_dob": "12/10/1982",
"student_email": "djones@school.ac.uk"
}
puisque le nom de la propriété de niveau supérieur est l'identifiant de l'étudiant, vous pouvez utiliser une carte au lieu d'une structure
type id struct {
record map[string]record
}
et assurez-vous que vous n'avez pas de virgules de fin car cela n'est pas autorisé dans les spécifications json
L'enregistrement a également une incohérence de nom de champ, vous devrez donc également ajouter des balises struct à ces champs pour résoudre le problème.
Tout d'abord, votre JSON n'est pas valide.
Contrairement aux structures GoLang, vous n'avez pas besoin de mettre , après votre objet final.
{
"394885":
{
"record":
{
"nom_étudiant": "Daryl Jones",
"numéro_étudiant": 123884,
"student_dob": "12/10/1982",
"Student_email": "djones@school.ac.uk"
}
}
}
Deuxièmement,
var records censés modéliser votre JSON exactement, soit en nommant les champs de votre structure exactement comme ils sont nommés dans l'objet JSON, soit en utilisant des attributs.
L'extérieur de votre JSON n'est pas de type id , il est de type map[string id
id n'a pas de Champ recordid , il possède cependant un champ record , mais le champ de vos structures doit être exporté (commencez par une majuscule) si vous souhaitez sérialiser JSON dans ces derniers .
C'est là que les attributs sont utiles,
type record struct {
Name string `json:"student_name"`
Email string `json:"student_email"`
// You get the idea...
}
Idem avec la structure record ,
type id struct {
Record []record `json:"record"`
}
Troisièmement,
Vous mettez l'instruction defer juste après avoir ouvert le fichier,
le mettre à la fin du bloc va à l'encontre du but.
Déclarez les types Go qui correspondent à la structure des données. Les données JSON ont trois niveaux d'objets. Utilisez une carte pour représenter l'objet de niveau supérieur dans le JSON, car l'objet de niveau supérieur possède des clés arbitraires. Utilisez des structures pour les objets de niveau inférieur dans le JSON.
Utilisez les balises de champ JSON pour mapper les noms de cas de serpent utilisés dans le JSON à des noms Go plus idiomatiques. Exportez les champs afin qu'ils soient accessibles par le package JSON.
Consultez la documentation de la fonction Marshal pour savoir comment le package json / encoding utilise les balises de champ et les exigences pour exporter les champs.
type Record struct {
Name string `json:"student_name"`
Number uint32 `json:"student_number"`
DOB string `json:"student_dob"`
Email string `json:"student_email"`
}
type ID struct {
Record Record
}
...
var records map[string]ID
err := json.Unmarshal(jsonFile, &records)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", records)
Le package
jsonquery peut facilement extraire des données d'un document JSON, et il ne dépend pas de la structure définie objet.
func main() {
s := `{
"394885":
{
"record":
{
"student_name": "Daryl Jones",
"student_number": 123884,
"student_dob": "12/10/1982",
"student_email": "djones@school.ac.uk"
}
}
}`
doc, err := jsonquery.Parse(strings.NewReader(s))
if err != nil {
panic(err)
}
nodes := jsonquery.Find(doc, "*")
for _, n := range nodes {
fmt.Printf("id: %s \n", n.Data)
name := jsonquery.FindOne(n, "//student_name") // Find student name node
fmt.Printf("student name: %s\n", name.InnerText())
number := jsonquery.FindOne(n, "//student_number") // Find node for student number
fmt.Printf("student number: %s\n", number.InnerText())
}
}