JSON を扱うというと単純明快に聞こえるかもしれませんが、いくつかの構造体があるので、それを JSON (一般的な統一言語) に変更して構造体に戻すことができます。シンプルですよね? ?
そうですね、そうですが、それはマーシャル/アンマーシャル関数からの奇妙な動作に遭遇するまでの話です。
すべては、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 として解析しており、データの読み取り時に問題が発生します。
この問題を解決するには実際には 2 つの方法があります
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 の方が優れているのではないかと思うかもしれません。
そうですね、それは状況によります。構造体から 1 つの属性を読み取るための構造体を常に作成したいとは限りません。そのため、正しい答えは -- 状況によります!
今日の記事はこれで終わりだと思います。ゴーファーさん、何か新しいことを学んでいただければ幸いです?.
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3