Working with JSON can sound simple & clear, you have some struct, you can change it to JSON — A general unified language & back to your struct. Simple right? ?
Well, yeah, but that's until you encounter some weird behavior from the Marshal / Unmarshal functions.
It all started when I was trying to read the encoded payload from a JWT token, below is an example that demonstrates the issue
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) }
Just marshaling and unmarshaling back out struct, so it's expected to return the same value!
Unfortunately, this didn't happen, the code above outputs
// Result id: 0 Ok:false post_ids: [] Ok:false
Once I saw that output, I ? the issue might be with type conversions, so I went to check what types does these interfaces have
fmt.Printf("id: %T\n", m["id"]) fmt.Printf("post_ids: %T\n", m["post_ids"])
// Result id: float64 post_ids: []interface {}
So as we can see, JSON has parsed out int64 as float64, which lead to issues upon reading the data.
There is actually 2 ways to fix this issue
Use type assertions of float64, Notice that []interface{} can't be mapped right away to []float64, so we have to iterate each element and convert it
// 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]
Parse it back to a struct
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)
Of course, you might think, why should we even use Solution 01, isn't Solution 02 better?
Well it depends, you don't always want to create a struct to read a single attribute from a struct, so the correct answer is -- It depends!
I think that's all for today's article, wish you learned something new, my fellow gopher ?.
The above is the detailed content of The Mystery Of JSON Conversion Of IntTo Float64. For more information, please follow other related articles on the PHP Chinese website!