IntTo Float64 の JSON 変換の謎

WBOY
リリース: 2024-09-03 13:20:19
オリジナル
1135 人が閲覧しました

The Mystery Of JSON Conversion Of IntTo Float64

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 つの方法があります

?解決策 01 (困難な方法)

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]
ログイン後にコピー

?解決策 02 (簡単な方法)

解析して構造体に戻します

    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 つの属性を読み取るために構造体を作成したいとは限らないため、正しい答えは -- 状況によります!

今日の記事はこれで終わりだと思います。ゴーファーさん、何か新しいことを学んでいただければ幸いです。

以上がIntTo Float64 の JSON 変換の謎の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート