最近在golang业务开发时,遇到一个坑。
我们有个服务,会接收通用的interface对象,然后去给用户发消息。因此会涉及到把各个业务方传递过来的字符串,转成interface对象。
但是因为我的字符串里有一个数字,比如下面demo里的{"number":1234567}
,而且数字是7位数,在经过json.Unmarshal
后,被转成了科学计数法的形式,导致私信发出的链接出现异常,结果报错了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package main
import (
"encoding/json"
"fmt"
)
func main() {
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]
}
|
当数据结构未知,使用 map[string]interface{}
来接收反序列化结果时,如果数字的位数大于 6 位,都会变成科学计数法,用到的地方都会受到影响。
从encoding/json
包中,可以找到下面一段注释:
1 2 3 4 5 6 7 8 9 10 11 |
//
// 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
//
|
对于数字来说,会被解析成 float64
类型,就有可能会出现科学计数法的形式。
问题解决方案1:强制类型转换
1 2 3 4 5 6 7 8 9 10 11 12 |
func main() {
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
}
|
问题解决方案2:尽量避免使用 interface
,对 json
字符串结构定义结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
func main() {
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}
}
|