沙滩星空的博客沙滩星空的博客

总结golang解析json字符串出现的坑

长整型数字精度丢失

import (
    "bytes"
    "encoding/json"
)

...
const userJson=`{"name":"Harvey","id":1514889703642370048}`
userInfo map[string]interface{}
infoBytes := []byte(userJson)
json.Unmarshal(infoBytes, &userInfo)
// json数值类型被定义为 interface{}, 使用 Unmarshal 方法后,只能被断言为float64
uid := userInfo["id"].(float64)

func JsonDecodeUseNumber(infoBytes []byte, result interface{}) error {    
    decoder := json.NewDecoder(bytes.NewReader(infoBytes))
    // 未设置UseNumber, 长整型会丢失精度
    decoder.UseNumber()
    return decoder.Decode(result)
}

JsonDecodeUseNumber(infoBytes, &userInfo)
uidJNum := userInfo["id"].(json.Number)
uid := uidJNum.Int64()
...
  1. json 没有整型和浮点型之分, 只有 Number 数值类型
  2. json 中的 Number 字段,如果被定义为 interface{}, 使用 json.Unmarshal 方法将被解析为 float64
  3. 使用 UseNumber() 方法,将 interface{} 类型,转为 json.Number 类型

该问题实质为 IEEE754 二进制浮点数算术标准(ANSI/IEEE Std 754-1985)的问题。

json字符串包含非法字符

json.Unmarshal 解压报错: json.Unmarshal invalid character '\n' in string literal

import (
    "bytes"
    "encoding/json"
)

...
prodJson := `{"hel": "doafd",
"xxxdf": "aoifjadfoweih"}`
prodBytes := []byte(prodJson)
for i, ch := range prodBytes {
    switch {
        case ch > '~':
    prodBytes[i] = ' '
    case ch == '\r', ch == '\n', ch == '\t', ch < ' ':
    prodBytes[i] = ' '
    }
}
pd := map[string]string{}
json.Unmarshal(prodBytes, &pd)
...

json中非法字符


golang——Json分级解析及数字解析实践 https://www.jianshu.com/p/8b64bb06d522
Go 易采坑总结 https://www.liuin.cn/2018/08/23/Go-%E6%98%93%E9%87%87%E5%9D%91%E6%80%BB%E7%BB%93/
深入理解 Go Json.Unmarshal 精度丢失之谜 https://developer.51cto.com/article/697019.html
未经允许不得转载:沙滩星空的博客 » 总结golang解析json字符串出现的坑

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址