Golang中如何保持map[string]interface{}的int64值
Golang中如何保持map[string]interface{}的int64值 大家好,
我遇到了一个问题(我必须保持通用形式,因为我将此方法用于所有类型的查询):
genericBody = map[string]interface{}{}
dec := json.NewDecoder(genericResp.Body)
err = dec.Decode(&genericBody)
它将这个:
{
"data": {
"list": [
{
"advertiser_id": 6868310788839309317,
"advertiser_name": "fggddf"
}
]
},
}
转换为:
{
"data":{
"list":[
{
"advertiser_id":6868310788839309000,
"advertiser_name":"fggddf"
}
]
},
}
这个: 6868310788839309000 变成了: 6868310788839309317
看起来它没有保留完整的 int64 值…
更多关于Golang中如何保持map[string]interface{}的int64值的实战教程也可以访问 https://www.itying.com/category-94-b0.html
非常感谢
更多关于Golang中如何保持map[string]interface{}的int64值的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
哇,非常感谢你的解释
这很可能是因为JSON本质上与JavaScript及其缺陷紧密耦合。
如果你需要精确的数字,请使用字符串。
json.NewDecoder
我自动回复:
dec := json.NewDecoder(genericResp.Body)
dec.UseNumber()
err = dec.Decode(&genericBody)
在向客户端写入有效载荷时仍然存在问题:
{
"ads_provider_profiles": [
{
"id": 6868310788839309000,
}
]
}

在处理JSON中的数字时,应始终使用“大数”,在Go语言中这意味着使用 math/big 包。
big package - math/big - pkg.go.dev
Package big implements arbitrary-precision arithmetic (big numbers).
否则,将它们编码为 string 类型,就无需担心IEEE浮点数转换的问题。
NobbZ:
它的缺陷
Number.MAX_SAFE_INTEGER - JavaScript | MDN
Number.MAX_SAFE_INTEGER 静态数据属性表示 JavaScript 中的最大安全整数 (2^53 – 1)。
9007199254740991,这远小于原帖中的数字 6868310788839309317。
然而,6868310788839309317 的十六进制表示为 0x5f512445c7c00005。由于末尾的 5 前面有那么多零,这些零可以被浮点数指数部分吸收,这意味着从 int64 到 float64 再转换回来只会丢失最后的 5。
package main
import "fmt"
func main() {
n := 6868310788839309317
jsmaxint := 9007199254740991
fmt.Println(jsmaxint)
fmt.Println(n)
fmt.Println(int64(float64(n)))
fmt.Printf("%x\n", n)
fmt.Printf("%x\n", int64(float64(n)))
}
9007199254740991
6868310788839309317
6868310788839309312
5f512445c7c00005
5f512445c7c00000
在Go中,当使用json.Unmarshal或json.Decode到map[string]interface{}时,JSON中的数字默认会被解析为float64类型。由于浮点数的精度限制,大整数可能会丢失精度。
解决方案:使用json.Decoder的UseNumber()方法
package main
import (
"encoding/json"
"fmt"
"strings"
)
func main() {
jsonStr := `{
"data": {
"list": [
{
"advertiser_id": 6868310788839309317,
"advertiser_name": "fggddf"
}
]
}
}`
// 方法1:使用UseNumber()
genericBody := map[string]interface{}{}
dec := json.NewDecoder(strings.NewReader(jsonStr))
dec.UseNumber() // 关键:使用Number类型而不是float64
err := dec.Decode(&genericBody)
if err != nil {
panic(err)
}
// 提取并转换数字
data := genericBody["data"].(map[string]interface{})
list := data["list"].([]interface{})
item := list[0].(map[string]interface{})
// 将json.Number转换为int64
idStr := item["advertiser_id"].(json.Number)
idInt64, err := idStr.Int64()
if err != nil {
panic(err)
}
fmt.Printf("原始值: %v\n", idStr)
fmt.Printf("int64值: %d\n", idInt64)
fmt.Printf("完整精度: %d\n", idInt64)
}
处理嵌套结构的通用方法
func decodeWithFullPrecision(body io.Reader) (map[string]interface{}, error) {
genericBody := map[string]interface{}{}
dec := json.NewDecoder(body)
dec.UseNumber()
err := dec.Decode(&genericBody)
if err != nil {
return nil, err
}
// 递归处理所有数字
processNumbers(genericBody)
return genericBody, nil
}
func processNumbers(data interface{}) {
switch v := data.(type) {
case map[string]interface{}:
for key, val := range v {
switch val := val.(type) {
case json.Number:
// 尝试转换为int64,如果失败则保持为string
if intVal, err := val.Int64(); err == nil {
v[key] = intVal
} else if floatVal, err := val.Float64(); err == nil {
v[key] = floatVal
}
default:
processNumbers(val)
}
}
case []interface{}:
for i, item := range v {
processNumbers(item)
}
}
}
使用自定义类型保持灵活性
type FlexibleMap map[string]interface{}
func (fm *FlexibleMap) UnmarshalJSON(data []byte) error {
var temp map[string]interface{}
dec := json.NewDecoder(bytes.NewReader(data))
dec.UseNumber()
if err := dec.Decode(&temp); err != nil {
return err
}
// 转换所有json.Number为合适的类型
convertNumbers(temp)
*fm = temp
return nil
}
func convertNumbers(m map[string]interface{}) {
for k, v := range m {
switch val := v.(type) {
case json.Number:
// 尝试int64,然后float64,最后保持string
if i, err := val.Int64(); err == nil {
m[k] = i
} else if f, err := val.Float64(); err == nil {
m[k] = f
} else {
m[k] = val.String()
}
case map[string]interface{}:
convertNumbers(val)
case []interface{}:
for i, item := range val {
if subMap, ok := item.(map[string]interface{}); ok {
convertNumbers(subMap)
}
}
}
}
}
在你的代码中直接应用
genericBody := map[string]interface{}{}
dec := json.NewDecoder(genericResp.Body)
dec.UseNumber() // 添加这一行
err = dec.Decode(&genericBody)
// 现在可以安全地提取大整数
data := genericBody["data"].(map[string]interface{})
list := data["list"].([]interface{})
for _, item := range list {
advertiser := item.(map[string]interface{})
if id, ok := advertiser["advertiser_id"].(json.Number); ok {
fullInt64, _ := id.Int64()
fmt.Printf("完整int64值: %d\n", fullInt64)
}
}
使用dec.UseNumber()后,JSON中的数字会被解析为json.Number类型(本质上是string),然后可以通过Int64()、Float64()或String()方法按需转换,从而保持完整的精度。

