1.问题现象描述

使用 json.Unmarshal(),反序列化时,出现了科学计数法,参考代码如下:

jsonStr := `{"number":1234567}`
result := make(map[string]interface{})
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
fmt.Println(err)
}
fmt.Println(result) // 输出
// map[number:1.234567e+06]

这个问题不是必现,只有当数字的位数大于 6 位时,才会变成了科学计数法。

2.问题影响描述

当数据结构未知,使用 map[string]interface{} 来接收反序列化结果时,如果数字的位数大于 6 位,都会变成科学计数法,用到的地方都会受到影响。

3.引起问题的原因

encoding/json 可以找到答案,看一下这段注释:

// To unmarshal JSON into an interface value,
// Unmarshal stores one of these in the interface value:
//
// bool, for JSON booleans
// float64, for JSON numbers
// string, for JSON strings
// []interface{}, for JSON arrays
// map[string]interface{}, for JSON objects
// nil for JSON null

是因为当 JSON 中存在一个比较大的数字时,它会被解析成 float64 类型,就有可能会出现科学计数法的形式。

4.问题的解决方案

方案一

强制类型转换,参考代码如下:

jsonStr := `{"number":1234567}`
result := make(map[string]interface{})
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
fmt.Println(err)
}
fmt.Println(int(result["number"].(float64))) // 输出
// 1234567

方案二

尽量避免使用 interface,对 json 字符串结构定义结构体,快捷方法可使用在线工具:https://mholt.github.io/json-to-go/

type Num struct {
Number int `json:"number"`
} jsonStr := `{"number":1234567}`
var result Num
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
fmt.Println(err)
}
fmt.Println(result) // 输出
// {1234567}

方案三

使用 UseNumber() 方法。

jsonStr := `{"number":1234567}`
result := make(map[string]interface{})
d := json.NewDecoder(bytes.NewReader([]byte(jsonStr)))
d.UseNumber()
err := d.Decode(&result)
if err != nil {
fmt.Println(err)
}
fmt.Println(result) // 输出
// map[number:1234567]

这时一定要注意 result["number"] 的数据类型!

fmt.Println(fmt.Sprintf("type: %v", reflect.TypeOf(result["number"])))

// 输出
// type: json.Number

通过代码可以看出 json.Number 其实就是字符串类型:

// A Number represents a JSON number literal.
type Number string

如果转换其他类型,参考如下代码:

// 转成 int64
numInt, _ := result["number"].(json.Number).Int64()
fmt.Println(fmt.Sprintf("value: %v, type: %v", numInt, reflect.TypeOf(numInt))) // 输出
// value: 1234567, type: int64 // 转成 string
numStr := result["number"].(json.Number).String()
fmt.Println(fmt.Sprintf("value: %v, type: %v", numStr, reflect.TypeOf(numStr))) // 输出
// value: 1234567, type: string

最新文章

  1. 干货来袭-整套完整安全的API接口解决方案
  2. kaggle数据挖掘竞赛初步--Titanic<派生属性&维归约>
  3. java基础-servlet-1
  4. sublime text 3 的在文件夹中查找的快捷键没有反应 的bug冲突
  5. [转]MVC、MVP、MVVM
  6. BZOJ1829 : [Usaco2010 Mar]starc星际争霸
  7. HDU-4750 Count The Pairs 最小生成树,并查集
  8. 设计模式之Prototype(c++)
  9. 怎么样putty打开图形化管理工具,在终端上
  10. Spring Boot 学习(1)
  11. MySQL 主从复制与读写分离概念及架构分析 (转)
  12. 在实战中使用Sass和Compass
  13. 新版Azure Automation Account 浅析(一) --- 创建和Run As Account
  14. win 10 和 CentOS 7 双系统安装
  15. 1、阿里云ECS内部机器端口被100.117.90段的ip疯狂扫描导致业务异常
  16. 咱家自己的vim配置
  17. javascript转义unicode十六进制编码且带有反斜杠后的html
  18. Linux下用node-inspector实现NodeJS远程调试开发
  19. csv文件的读取
  20. \G 用法:查询结果按列打印

热门文章

  1. SpringMVC+Mybatis初尝试
  2. [AGC043-D]Merge Triplets
  3. MongoDB——基本使用及集群搭建
  4. OO第一单元——谜之随性总结
  5. cb48a_c++_STL_算法_重排和分区random_shuffle_stable_partition
  6. Java基本数据类型和包装类
  7. Java技术开发标准JSR介绍
  8. 流媒体学习计划表——pr
  9. 【解读】TCP粘包拆包
  10. HttpClient优化