例如有一个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去接收数据怎么办?

有几个坑需要注意一下:

  1. JSON的规范中,对于数字类型,并不区分是整型还是浮点型。

  2. 如果反序列化不指定结构体类型或者变量类型,则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。