例如有一个json数据:
1
2
3
4
5
6
7
8
9
|
{
"name": "小明",
"money": 1111111111111111111
}
|
但是小明很有钱,他的钱用int64是存储不下来的,如果我们用一个结构体来接受数据就很简单,例如:
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package main
import (
"encoding/json"
"fmt"
)
type Info struct {
Name string `json:"name"`
Money uint64 `json:"money"`
}
func main() {
info := &Info{}
json.Unmarshal([]byte(`
{
"name": "小明",
"money": 1111111111111111111
}`), info)
fmt.Println(info)
}
|
但是在某些情况下,你不得不用一个map去接收数据怎么办?
有几个坑需要注意一下:
-
JSON的规范中,对于数字类型,并不区分是整型还是浮点型。
-
如果反序列化不指定结构体类型或者变量类型,则JSON中的数字类型,默认被反序列化成float64类型
如何解决这个问题,先看下面程序:
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package main
import (
"encoding/json"
"fmt"
"strconv"
"strings"
)
func main() {
const jsonStream = `
{
"name": "小明",
"money": 1111111111111111111
}
`
decoder := json.NewDecoder(strings.NewReader(jsonStream))
decoder.UseNumber() // UseNumber causes the Decoder to unmarshal a number into an interface{} as a Number instead of as a float64
info := map[string]interface{}{}
decoder.Decode(&info)
money := info["money"].(json.Number).String()
fmt.Println(money)
m, _ := strconv.ParseUint(money, 10, 64)
fmt.Println(m)
}
|
上面的程序,使用了func (*Decoder) UseNumber方法告诉反序列化JSON的数字类型的时候,不要直接转换成float64,而是转换成json.Number类型。json.Number本质是字符串,反序列化的时候将JSON的数值先转成json.Number,其实是一种延迟处理的手段,待后续逻辑需要时候,再把json.Number转成float64或者int64。