当前位置: 首页 > 编程笔记 >

Go 语言json.Unmarshal 遇到的小问题(推荐)

宋涵忍
2023-03-14
本文向大家介绍Go 语言json.Unmarshal 遇到的小问题(推荐),包括了Go 语言json.Unmarshal 遇到的小问题(推荐)的使用技巧和注意事项,需要的朋友参考一下

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

到此这篇关于Go 语言json.Unmarshal 遇到的小问题(推荐)的文章就介绍到这了,更多相关Go 语言json.Unmarshal内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!

 类似资料:
  • 1.问题现象描述 使用 json.Unmarshal(),反序列化时,出现了科学计数法,参考代码如下: jsonStr := `{"number":1234567}` result := make(map[string]interface{}) err := json.Unmarshal([]byte(jsonStr), &result) if err != nil { fmt.Print

  • 本文向大家介绍MybatisPlus使用代码生成器遇到的小问题(推荐),包括了MybatisPlus使用代码生成器遇到的小问题(推荐)的使用技巧和注意事项,需要的朋友参考一下 MybatisPlus 给我们提供了更加强大的代码生成器 MyBatisPlus 在3.0.3版本之前使用代码生成器因为存在默认依赖,所以不需要其他的依赖,项目中使用的是3.0.1的版本,所以不用添加其他依赖,添加之后反倒是

  • 各位大佬们,当我在构建docker容器的时候意外遇到了这个错误,想问问各位如何解决 其中docker报错

  • 用的vue3 和element plus,在代码中 每次code1获取到的值都是上一次存入的值,网上搜说是因为异步的关系,具体应该怎么修改请大佬指导!

  • 我应该编写一个函数来合并(将一个放在另一个的末尾)两个单独链接的列表。用户向控制台输入一系列数字,例如:1 2 3 4 0(0表示输入结束,不是列表中的元素)。这些数字被放入链表中,链表现在看起来是这样的:1 2 3 4。这个过程再次重复,直到我们有两个不同的链表。然后,合并函数被称为“void merge(结构节点头1,结构节点头2)”。打印新列表后,程序结束。 我的想法是首先将指针指向第一个列

  • 如果我注释了三个操作中的两个,那么无论wich,编译都很好。 我将语法转换为Java,并按照Antlr4网站中的教程进行编译:在时,我会得到相同的错误,但会指示错误94,action_redefinition。 我尝试用antlr版本4.1和版本4.2编译。