亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

搜索

Go中解析JSON時保留64位整數(shù)值的方法

花韻仙語
發(fā)布: 2025-10-16 11:30:13
原創(chuàng)
134人瀏覽過

Go中解析JSON時保留64位整數(shù)值的方法

go語言中處理json數(shù)據(jù)時,當(dāng)使用`json.unmarshal`將包含大整數(shù)(如64位整數(shù))的json解析到`map[string]interface{}`時,這些整數(shù)可能會被默認(rèn)轉(zhuǎn)換為`float64`,導(dǎo)致精度丟失。本文將詳細(xì)介紹兩種有效方法來避免這種問題:一是利用`json.decoder`的`usenumber()`方法將數(shù)字解析為`json.number`類型,再手動轉(zhuǎn)換;二是定義明確的go結(jié)構(gòu)體,直接將大整數(shù)類型指定為`uint64`或`int64`進(jìn)行解碼。

在Go語言的encoding/json包中,當(dāng)使用json.Unmarshal將JSON數(shù)據(jù)解析到interface{}類型(例如map[string]interface{})時,它會將JSON中的數(shù)字字面量默認(rèn)解析為Go的float64類型。對于不超出float64精度范圍的整數(shù)而言,這通常不是問題。然而,當(dāng)JSON中包含的整數(shù)值超過float64所能精確表示的最大整數(shù)(即2^53)時,就會發(fā)生精度丟失。例如,一個64位整數(shù)(如4418489049307132905)在轉(zhuǎn)換為float64后,其低位信息可能會被截斷或四舍五入。

以下是兩種在Go中解析JSON時保留64位整數(shù)值的解決方案。

解決方案一:使用 json.Decoder 和 UseNumber()

encoding/json包提供了一個Decoder類型,它比直接使用json.Unmarshal提供了更精細(xì)的控制。通過Decoder的UseNumber()方法,我們可以指示解碼器將所有JSON數(shù)字解析為json.Number類型,而不是默認(rèn)的float64。json.Number實際上是一個字符串類型,它保留了數(shù)字的原始字符串表示,從而避免了任何潛在的精度損失。之后,我們可以根據(jù)需要將其轉(zhuǎn)換為int64或uint64。

示例代碼

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "strconv"
)

func main() {
    body := []byte(`{"tags":[{"id":4418489049307132905},{"id":4418489049307132906}]}`)

    // 創(chuàng)建一個map來存儲解析后的數(shù)據(jù)
    dat := make(map[string]interface{})

    // 創(chuàng)建一個新的JSON解碼器
    d := json.NewDecoder(bytes.NewBuffer(body))

    // 啟用UseNumber(),將所有數(shù)字解析為json.Number類型
    d.UseNumber()

    // 解碼JSON數(shù)據(jù)
    if err := d.Decode(&dat); err != nil {
        panic(err)
    }

    // 訪問解析后的數(shù)據(jù)
    tags, ok := dat["tags"].([]interface{})
    if !ok {
        panic("tags not found or not an array")
    }

    // 遍歷標(biāo)簽并處理ID
    for i, tag := range tags {
        tagMap, ok := tag.(map[string]interface{})
        if !ok {
            fmt.Printf("tag %d is not a map\n", i)
            continue
        }

        idNum, ok := tagMap["id"].(json.Number)
        if !ok {
            fmt.Printf("tag %d id is not a json.Number\n", i)
            continue
        }

        // 將json.Number轉(zhuǎn)換為uint64
        // 根據(jù)實際數(shù)據(jù)范圍選擇ParseInt或ParseUint
        id64, err := strconv.ParseUint(string(idNum), 10, 64)
        if err != nil {
            fmt.Printf("Error parsing id %s: %v\n", idNum, err)
            continue
        }
        fmt.Printf("tag: %d id: %d (Type: %T)\n", i, id64, id64)
    }
}
登錄后復(fù)制

工作原理

  1. json.NewDecoder(bytes.NewBuffer(body)):創(chuàng)建一個Decoder實例,從字節(jié)切片中讀取JSON數(shù)據(jù)。
  2. d.UseNumber():這是關(guān)鍵步驟。它告訴解碼器將JSON中的所有數(shù)字作為json.Number類型進(jìn)行處理。json.Number本質(zhì)上是一個string別名,存儲了數(shù)字的原始文本表示。
  3. d.Decode(&dat):執(zhí)行解碼操作。
  4. tagMap["id"].(json.Number):在訪問id字段時,需要將其斷言為json.Number類型。
  5. strconv.ParseUint(string(idNum), 10, 64):將json.Number(其底層是字符串)轉(zhuǎn)換為uint64類型。10表示十進(jìn)制,64表示目標(biāo)位寬。如果數(shù)字可能為負(fù)數(shù),應(yīng)使用strconv.ParseInt。

這種方法提供了最大的靈活性,但需要額外的類型斷言和字符串轉(zhuǎn)換步驟。

Find JSON Path Online
Find JSON Path Online

Easily find JSON paths within JSON objects using our intuitive Json Path Finder

Find JSON Path Online30
查看詳情 Find JSON Path Online

解決方案二:解碼到自定義結(jié)構(gòu)體

更Go慣用且通常更推薦的方法是定義一個與JSON結(jié)構(gòu)相匹配的Go結(jié)構(gòu)體(struct)。通過明確指定結(jié)構(gòu)體字段的類型為uint64或int64,json.Unmarshal可以直接將JSON中的數(shù)字解析到這些字段,而無需經(jīng)過float64的中間轉(zhuǎn)換。

示例代碼

package main

import (
    "encoding/json"
    "fmt"
)

// 定義與JSON結(jié)構(gòu)對應(yīng)的Go結(jié)構(gòu)體
type Tag struct {
    ID uint64 `json:"id"` // 明確指定ID為uint64類型
}

type Data struct {
    Tags []Tag `json:"tags"` // 包含Tag結(jié)構(gòu)體的切片
}

func main() {
    body := []byte(`{"tags":[{"id":4418489049307132905},{"id":4418489049307132906}]}`)

    var data Data
    // 直接將JSON數(shù)據(jù)解碼到自定義結(jié)構(gòu)體
    if err := json.Unmarshal(body, &data); err != nil {
        panic(err)
    }

    // 訪問解析后的數(shù)據(jù)
    for i, tag := range data.Tags {
        fmt.Printf("tag: %d id: %d (Type: %T)\n", i, tag.ID, tag.ID)
    }
}
登錄后復(fù)制

工作原理

  1. 定義結(jié)構(gòu)體:創(chuàng)建Tag和Data結(jié)構(gòu)體,它們的字段名稱和類型與JSON數(shù)據(jù)中的鍵和值相匹配。
  2. 類型指定:將Tag結(jié)構(gòu)體中的ID字段明確指定為uint64(或int64)。json:"id"是結(jié)構(gòu)體標(biāo)簽,用于將JSON鍵id映射到Go結(jié)構(gòu)體字段ID。
  3. 直接解碼:使用json.Unmarshal(body, &data)將JSON數(shù)據(jù)直接解碼到Data類型的變量中。

這種方法更具結(jié)構(gòu)化,代碼更簡潔,類型安全,且易于維護(hù)。對于已知JSON結(jié)構(gòu)的場景,這是首選方案。

注意事項

  • JavaScript的限制:如果您的應(yīng)用程序涉及到JavaScript,需要注意JavaScript標(biāo)準(zhǔn)中沒有64位整數(shù)類型,它只有IEEE 754雙精度浮點(diǎn)數(shù)。這意味著,即使您在Go中正確處理了64位整數(shù),當(dāng)這些數(shù)據(jù)傳遞到JavaScript前端時,如果直接使用標(biāo)準(zhǔn)的JSON解析函數(shù),仍然可能丟失精度。在JavaScript中處理大整數(shù)通常需要特殊的庫(如BigInt)或?qū)⒋笳麛?shù)作為字符串進(jìn)行傳輸。
  • 選擇方案
    • 當(dāng)JSON結(jié)構(gòu)未知或高度動態(tài)時,json.Decoder配合UseNumber()提供了更大的靈活性。
    • 當(dāng)JSON結(jié)構(gòu)已知且穩(wěn)定時,解碼到自定義結(jié)構(gòu)體是更清晰、更類型安全且易于維護(hù)的選擇。

總結(jié)

在Go語言中解析JSON數(shù)據(jù)時,為了避免64位整數(shù)值在默認(rèn)解碼過程中被轉(zhuǎn)換為float64并導(dǎo)致精度丟失,我們有兩種主要的策略。第一種是利用json.Decoder的UseNumber()方法將數(shù)字解析為json.Number字符串,然后手動轉(zhuǎn)換為int64或uint64。第二種是定義與JSON結(jié)構(gòu)相對應(yīng)的Go結(jié)構(gòu)體,并明確指定大整數(shù)字段的類型為int64或uint64。這兩種方法都能有效解決精度問題,開發(fā)者應(yīng)根據(jù)實際需求和JSON結(jié)構(gòu)的復(fù)雜性選擇最合適的方案。

以上就是Go中解析JSON時保留64位整數(shù)值的方法的詳細(xì)內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!

最佳 Windows 性能的頂級免費(fèi)優(yōu)化軟件
最佳 Windows 性能的頂級免費(fèi)優(yōu)化軟件

每個人都需要一臺速度更快、更穩(wěn)定的 PC。隨著時間的推移,垃圾文件、舊注冊表數(shù)據(jù)和不必要的后臺進(jìn)程會占用資源并降低性能。幸運(yùn)的是,許多工具可以讓 Windows 保持平穩(wěn)運(yùn)行。

下載
來源:php中文網(wǎng)
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn
最新問題
開源免費(fèi)商場系統(tǒng)廣告
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關(guān)于我們 免責(zé)申明 意見反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長!
關(guān)注服務(wù)號 技術(shù)交流群
PHP中文網(wǎng)訂閱號
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號