Gin中浮点数 NaN JSON序列化问题
作者:matrix 发布时间:2024-12-24 分类:Golang
无意把除数为0的计算放了进来,既然没有发现panic,页面却显示空白。看起来像是没有被全局recover捕获~
gin 控制台显示
Error #01: json: unsupported value: NaN
排查
断点调试下发现json处理的问题,error被push到gin的c.Error里面,gin被判定为私有类型错误,所以没有panic
~/go/pkg/mod/github.com/gin-gonic/gin@v1.10.0/context.go
func (c *Context) Render(code int, r render.Render) {
c.Status(code)
if !bodyAllowedForStatus(code) {
r.WriteContentType(c.Writer)
c.Writer.WriteHeaderNow()
return
}
if err := r.Render(c.Writer); err != nil {
// Pushing error to c.Errors
_ = c.Error(err)
c.Abort()
}
}
r.Render(c.Writer)
内部会json序列化,error被返回到r.Render。这个错误信息就直接给了上下文的c.Error(err)
原因
Json序列化时存在math.Nan
特殊浮点型数据会导response失败,
c.JSON
没有任何返回也就是空白页面显示了。
测试
func main() {
data := map[string]interface{}{
"name": "123",
"name_nan": math.NaN(), // json: unsupported value: NaN
// "name_inf": math.Inf(1), // json: unsupported value: +Inf
// "name_inf": math.Inf(-1), // json: unsupported value: -Inf
}
a, err := json.Marshal(data)
fmt.Println(a, err)
}
像NaN
这种其他特殊意义值 Inf
都回导致 JSON 序列化异常
解决办法
gin中添加错误处理中间件
func ErrorHandler() gin.HandlerFunc {
return func(c *gin.Context) {
c.Next() // 继续执行请求处理链
//中间件处理完成后进行错误收集
if len(c.Errors) > 0 {
// 迭代错误并处理
for _, err := range c.Errors {
c.JSON(http.StatusInternalServerError, gin.H{
"code": http.StatusInternalServerError,
"message": err.Error(),
"data": nil,
})
c.Abort()
return
}
}
}
}
其他办法就是自行实现JSON序列化操作或者判断NaN
、Inf
数据
参考:
https://blog.axiaoxin.com/post/2021-11-21-Golang-%E8%BF%90%E8%A1%8C%E6%97%B6%E9%99%A4%E6%95%B0%E4%B8%BA-0-%E8%BF%94%E5%9B%9E-inf/
https://blog.csdn.net/qq_36268452/article/details/124809417
https://blog.csdn.net/qq_40227117/article/details/122186916