子嘉的博客 子嘉的博客
首页
bic-bic
技术
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

高子嘉

没有比脚更长的路,没有比人更高的山
首页
bic-bic
技术
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术文档

  • GitHub技巧

  • 博客搭建

  • 服务端

  • distributed

  • golang

    • gomod
    • compile
    • code_snippet

      • json反序列化 int64丢失
        • 问题分析
        • 代码片段
      • 限流器
    • protobuf
    • 单元测试
    • script

  • db

  • docker

  • linux

  • 技术
  • golang
  • code_snippet
子嘉
2022-07-09
目录

json反序列化 int64丢失

# 问题分析

json数据反序列化时,在遇到定义中是interface{}时,对于数字类型,会转化成float64类型,从而导致如果数字类型的精度损失。查看json.Unmarshal源码发现下面代码片段

// convertNumber converts the number literal s to a float64 or a Number
// depending on the setting of d.useNumber.
func (d *decodeState) convertNumber(s string) (interface{}, error) {
	if d.useNumber {
		return Number(s), nil
	}
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeOf(0.0), Offset: int64(d.off)}
	}
	return f, nil
}
1
2
3
4
5
6
7
8
9
10
11
12

# 代码片段

从代码中可见,在未设置 useNumber 时,默认对数字转化成了float64。从而可以通过设置 useNumber,解决精度丢失问题。示例代码如下

package main

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

type UserData struct {
	Value interface{} `json:"value"`
}

func TestName(t *testing.T) {
	data := &UserData{
		Value: 1<<63 - 1,
	}
	dataBytes, _ := json.Marshal(data)
	fmt.Println("json data: ", string(dataBytes))

	dataUnmarshal := &UserData{}
	dec := json.NewDecoder(bytes.NewBuffer(dataBytes))
	dec.UseNumber()
	_ = dec.Decode(dataUnmarshal)
	fmt.Println("json unmarshal use number: ", dataUnmarshal.Value)

	_ = json.Unmarshal(dataBytes, dataUnmarshal)
	fmt.Printf(fmt.Sprintf("json unmarshal normal: %v", dataUnmarshal.Value))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

输出结果如下

=== RUN   TestName
json data:  {"value":9223372036854775807}
json unmarshal use number:  9223372036854775807
json unmarshal normal: 9.223372036854776e+18--- PASS: TestName (0.00s)
PASS
1
2
3
4
5
编辑 (opens new window)
#golang
上次更新: 2023/02/24, 10:34:03
compile
限流器

← compile 限流器→

最近更新
01
mongodb restore
03-06
02
pytesseract
02-28
03
consul
02-24
更多文章>
Theme by Vdoing | Copyright © 2022-2025 子嘉 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式