先来看一下 : JSON number的那些事
golang 数据类型和json类型对照关系表:
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中没有int64类型的,反序列化的时候,如果直接用json.Unmarshal 可能会精度丢失
可以参考这篇文章:json 反序列化数字精度丢失
原理:
解析 JSON 的时候其实是对 JSON 串的遍历,其实所有遍历出来的值都是[]byte类型,然后根据识别目标解析对象字段类型,或者识别[]byte数据的内容转换格式。
比如,如果数据被解析到int上,把[]byte转换为int;
如果被解析到interface{}上,就只能通过[]byte的类型来转换了,
而且数字会被统一处理成float64,这个有个问题,就是会丢精度。
而通过Number解析时,值会被直接保存为字符串类型。
正确做法:
func DecodeMyStruct(jsonStr string) (*MyStruct, error) {
var regular *MyStruct
decoder := jsoniter.NewDecoder(strings.NewReader(jsonStr))
//使用UseNumber()可以使得json中的大整数转换时,不会转换成浮点数float64,但是要用decoder不能用json.Marshal
decoder.UseNumber()
err := decoder.Decode(®ular)
if err != nil {
return nil, err
}
return ®ular, nil
}
其中 MyStruct是我们需要反序列化的类型,可以是struct,slice, map等等.
如果不知道应该反序列化成啥类型,可以是map[string]interface{}
,用的时候可以配合断言使用,
比如下面一种场景:需要对比两个json反序列化成map[string]interface{}
的结构,
判断:filterAttrMap 是不是包含 conditionMap的所有键值对。
func CompareRecursiveV2(ctx context.Context, filterAttrMap, conditionMap map[string]interface{