浅谈golang的json.Unmarshal的坑
知鱼君 人气:0最近在golang业务开发时,遇到一个坑。
我们有个服务,会接收通用的interface对象,然后去给用户发消息。因此会涉及到把各个业务方传递过来的字符串,转成interface对象。
但是因为我的字符串里有一个数字,比如下面demo里的{"number":1234567}
,而且数字是7位数,在经过json.Unmarshal
后,被转成了科学计数法的形式,导致私信发出的链接出现异常,结果报错了。
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
包中,可以找到下面一段注释:
// // 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:强制类型转换
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
字符串结构定义结构体
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} }
参考文档:https:
加载全部内容