Travailler avec JSON peut sembler simple et clair, vous avez une structure, vous pouvez la changer en JSON — Un langage général unifié et revenir à votre structure. Simple, non ? ?
Eh bien, oui, mais c'est jusqu'à ce que vous rencontriez un comportement étrange de la part des fonctions Marshal/Unmarshal.
Tout a commencé lorsque j'essayais de lire la charge utile codée à partir d'un jeton JWT. Vous trouverez ci-dessous un exemple illustrant le problème
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) }
Il suffit de marshaler et de démarshaler la structure, elle devrait donc renvoyer la même valeur !
Malheureusement, cela ne s'est pas produit, le code ci-dessus génère
// Result id: 0 Ok:false post_ids: [] Ok:false
Une fois que j'ai vu cette sortie, j'ai ? le problème pourrait venir des conversions de types, alors je suis allé vérifier quels types ont ces interfaces
fmt.Printf("id: %T\n", m["id"]) fmt.Printf("post_ids: %T\n", m["post_ids"])
// Result id: float64 post_ids: []interface {}
Comme nous pouvons le voir, JSON a analysé int64 en tant que float64, ce qui entraîne des problèmes lors de la lecture des données.
Il existe en fait 2 façons de résoudre ce problème
Utilisez les assertions de type de float64, notez que []interface{} ne peut pas être mappée immédiatement sur []float64, nous devons donc itérer chaque élément et le convertir
// 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]
Analysez-le en une structure
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)
Bien sûr, vous pourriez penser, pourquoi devrions-nous même utiliser la solution 01, la solution 02 n'est-elle pas meilleure ?
Eh bien, cela dépend, vous ne voulez pas toujours créer une structure pour lire un seul attribut d'une structure, donc la bonne réponse est : Cela dépend !
Je pense que c'est tout pour l'article d'aujourd'hui, j'aimerais que vous appreniez quelque chose de nouveau, mon cher Gopher ?.
Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.
Copyright© 2022 湘ICP备2022001581号-3