使用 JSON 聽起來簡單明了,你有一些結構,你可以將其更改為 JSON - 一種通用的統一語言並返回到你的結構。簡單吧? ?
嗯,是的,但是直到您遇到 Marshal / Unmarshal 函數的一些奇怪行為。
這一切都是從我嘗試從 JWT 令牌讀取編碼的有效負載時開始的,以下是演示該問題的範例
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) }
只是編組和解組返回結構,因此預計會傳回相同的值!
不幸的是,這並沒有發生,上面的程式碼輸出
// Result id: 0 Ok:false post_ids: [] Ok:false
一旦我看到那個輸出,我?問題可能出在型別轉換上,所以我去檢查這些介面有哪些類型
fmt.Printf("id: %T\n", m["id"]) fmt.Printf("post_ids: %T\n", m["post_ids"])
// Result id: float64 post_ids: []interface {}
所以我們可以看到,JSON將int64解析為float64,這導致讀取資料時出現問題。
其實有兩種方法可以解決這個問題
使用float64的類型斷言,注意[]interface{}不能立即映射到[]float64,所以我們必須迭代每個元素並將其轉換
// 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]
將其解析回結構體
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)
當然,你可能會想,為什麼我們還要使用解決方案01,解決方案02不是更好嗎?
好吧,這取決於,您並不總是想創建一個結構體來從結構體中讀取單個屬性,所以正確的答案是——這取決於!
我想這就是今天的文章的全部內容,希望你學到一些新東西,我的地鼠夥伴? .
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3