golang 使用gorequest 遇到的序列化的坑
golang 序列化的库没其他语言那么好用,然后就掉坑里了。
是用gorequest 库发现的,这个高start 的库,还是有些问题。我使用场景是这样的:
package main
import (
"fmt"
"github.com/parnurzeal/gorequest"
)
type InStruct struct {
Param float64
}
func main() {
postData := InStruct{Param: int64(72057594088097496)}
resp, bodyBytes, errs := gorequest.New().Get("http://127.0.0.1:8080").Query(postData).EndBytes()
fmt.Println(resp, bodyBytes, errs)
}
然后,我发送的数据变成了:Param=72057594088097500。相当于是数据被四舍五入了,一番追查,发现底层做了这个操作,把数据给变了:
func (s *SuperAgent) queryStruct(content interface{}) *SuperAgent {
if marshalContent, err := json.Marshal(content); err != nil {
s.Errors = append(s.Errors, err)
} else {
var val map[string]interface{}
if err := json.Unmarshal(marshalContent, &val); err != nil {// 这里就会丢精度
s.Errors = append(s.Errors, err)
} else {
for k, v := range val {
k = strings.ToLower(k)
var queryVal string
switch t := v.(type) {
case string:
queryVal = t
case float64:
queryVal = strconv.FormatFloat(t, 'f', -1, 64)
case time.Time:
queryVal = t.Format(time.RFC3339)
default:
j, err := json.Marshal(v)
if err != nil {
continue
}
queryVal = string(j)
}
s.QueryData.Add(k, queryVal)
}
}
}
return s
}
换句话说,就是讲数据由map[string]int64 变成map[string]interface{}, 然后,数据发生了变化。
json 在处理go的数据类型转换时,有个对应关系:
数据类型 | JSON | Golang |
---|---|---|
字串 | string | string |
整数 | number | int64 |
浮点数 | number | flaot64 |
数组 | arrary | slice |
对象 | object | struct |
布尔 | bool | bool |
空值 | null | nil |
在将数字类型unmarshal 转化为interface{} 的时候,默认会先使用浮点数转换,这样,可能会丢失精度。那如何处理?反序列化的时候,将数据类型转换为json.Number 就ok,这样数据会延迟转换,后面可以根据需要转换为int64 或者是 float ,也可以是string。
给个正确的例子,应该使用UseNumber 反序列化:
package main
import (
"bytes"
"encoding/json"
"fmt"
)
type Account struct {
Email string `json:"email"`
Password string `json:"password"`
Money int64 `json:"money"`
}
func main() {
account := Account{
Email: "137311107@qq.com",
Password: "123",
Money: int64(72057594088097496),
}
deal(account)
}
func deal(data interface{}) {
bdata, err := json.Marshal(data)
fmt.Printf("err %v, str %+v\n", err, string(bdata))
var val map[string]interface{}
d := json.NewDecoder(bytes.NewBuffer(bdata))
d.UseNumber()
err = d.Decode(&val)
fmt.Printf("err %v, str %+v\n", err, val)
}

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
为监控而生的多级缓存框架 layering-cache
简介 layering-cache是在Spring Cache基础上扩展而来的一个缓存框架,主要目的是在使用注解的时候支持配置过期时间。layering-cache其实是一个两级缓存,一级缓存使用Caffeine作为本地缓存,二级缓存使用redis作为集中式缓存。并且基于redis的Pub/Sub做缓存的删除,所以它是一个适用于分布式环境下的一个缓存系统。 支持 支持缓存监控统计 支持缓存过期时间在注解上直接配置 支持二级缓存的自动刷新(当缓存命中并发现缓存将要过期时会开启一个异步线程刷新缓存) 刷新缓存分为强刷新和软刷新,强刷新直接调用缓存方法,软刷新直接改缓存的时间 缓存Key支持SpEL表达式 新增FastJsonRedisSerializer,KryoRedisSerializer序列化,重写String序列化。 输出INFO级别的监控统计日志 二级缓存是否允许缓存NULL值支持配置 二级缓存空值允许配置时间倍率 集成 集成 Spring 4.x 引入layering-cache maven 方式 <dependency> <groupId>com.gi...
-
下一篇
Oracle推出轻量级Java微服务框架Helidon
近日,Oracle推出了一个新的开源框架Helidon,该项目是一个用于创建基于微服务的应用程序的Java库集合。和Payara Micro、Thorntail(之前的WildFly Swarm)、OpenLiberty、TomEE等项目一样,该项目也加入了MicroProfile家族。 Helidon最初被命名为J4C(Java for Cloud),其设计以简单、快速为目标,它包括两个版本:Helidon SE和Helidon MP。Helidon SE提供了创建微服务的三个核心API:Web服务器、配置和安全,用于构建基于微服务的应用程序,不需要应用服务器。Helidon MP支持用于构建基于微服务的应用程序的MicroProfile 1.1规范。 Web服务器 受NodeJS和其他Java框架的启发,Helidon的Web服务器是一个异步、反应性API,运行在Netty之上。WebServer接口包括对配置、路由、错误处理以及构建度量和健康端点的支持。 下面的示例代码演示了如何启动一个简单的Helidon Web服务器,在一个随机可用的端口上显示“It works!”: //...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- MySQL8.0.19开启GTID主从同步CentOS8
- MySQL数据库在高并发下的优化方案
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19