Die Arbeit mit JSON kann einfach und klar klingen, Sie haben eine Struktur, Sie können sie in JSON ändern – eine allgemein einheitliche Sprache und zurück zu Ihrer Struktur. Einfach, oder? ?
Nun ja, aber das ist so lange, bis Sie auf ein seltsames Verhalten der Marshal-/Unmarshal-Funktionen stoßen.
Alles begann, als ich versuchte, die codierte Nutzlast von einem JWT-Token zu lesen. Unten ist ein Beispiel, das das Problem veranschaulicht
package main import ( "encoding/json" "fmt" ) type User struct { ID int64 `json:"id"` PostIDs []int64 `json:"post_ids"` } func main() { u := User{ ID: 1, PostIDs: []int64{1, 2, 3}, } b, err := json.Marshal(u) if err != nil { panic(err) } m := make(map[string]interface{}) if err = json.Unmarshal(b, &m); err != nil { panic(err) } userID, ok := m["id"].(int64) fmt.Printf("id: %d\nOk:%t\n", userID, ok) fmt.Println() // spliter postIDs, ok := m["id"].([]int64) fmt.Printf("post_ids: %v\nOk:%t\n", postIDs, ok) }
Nur Marshalling und Unmarshaling der Struktur, daher wird erwartet, dass sie denselben Wert zurückgibt!
Leider ist dies nicht passiert, der obige Code gibt Folgendes aus:
// Result id: 0 Ok:false post_ids: [] Ok:false
Als ich diese Ausgabe gesehen habe, habe ich ? Das Problem könnte bei Typkonvertierungen liegen, also habe ich nachgesehen, welche Typen diese Schnittstellen haben
fmt.Printf("id: %T\n", m["id"]) fmt.Printf("post_ids: %T\n", m["post_ids"])
// Result id: float64 post_ids: []interface {}
Wie wir sehen können, hat JSON int64 als float64 geparst, was zu Problemen beim Lesen der Daten führte.
Es gibt eigentlich zwei Möglichkeiten, dieses Problem zu beheben
Verwenden Sie Typzusicherungen von float64. Beachten Sie, dass []interface{} nicht sofort []float64 zugeordnet werden kann, daher müssen wir jedes Element iterieren und konvertieren
// Parse UserID userID, _ := m["id"].(float64) fmt.Printf("id: %f\n", userID) fmt.Println() // spliter // Parse PostIDs postIDsArr, _ := m["post_ids"].([]interface{}) postIDs := make([]int64, len(postIDsArr)) for i, v := range postIDsArr { id, _ := v.(float64) // NOTICE: direct conversion to int64 won't work here! postIDs[i] = int64(id) } fmt.Printf("post_ids: %v\n", postIDs)
// Result id: 1.000000 post_ids: [1 2 3]
Parsen Sie es zurück in eine Struktur
b, err = json.Marshal(m) // m = map[string]interface{} if err != nil { panic(err) } var u2 User if err := json.Unmarshal(b, &u2); err != nil { panic(err) } fmt.Println(u2.ID) fmt.Println(u2.PostIDs)
Natürlich denken Sie vielleicht, warum sollten wir überhaupt Lösung 01 verwenden, ist Lösung 02 nicht besser?
Nun, es kommt darauf an, Sie möchten nicht immer eine Struktur erstellen, um ein einzelnes Attribut aus einer Struktur zu lesen, daher lautet die richtige Antwort: Es kommt darauf an!
Ich denke, das ist alles für den heutigen Artikel. Ich wünschte, du hättest etwas Neues gelernt, mein Gopher-Kollege?.
Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.
Copyright© 2022 湘ICP备2022001581号-3