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)

}

 

本文发表于2018年10月15日 17:00
(c)注:本文转载自https://my.oschina.net/u/2950272/blog/2245906,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 27 讨论 0 喜欢 0

讨论

周娱

君子和而不同
按照自己的方式,去度过人生

4601 1243832
抢先体验

扫码体验
趣味小程序
文字表情生成器

加入组织

扫码添加周娱微信
备注“加入组织”
邀请进开发群

闪念胶囊

不积跬步无以至千里,越焦虑越要扎实干。

不要试图鹤立鸡群,趁早离开那群鸡!

程序员过节需要的不是美女、不是美食、不是不加班!他们需要的是写代码,一群人写、往死里写、通宵写!!那种暗流涌动的狂欢,远比虚无庸俗的食色更让他们振奋!! by芋头

面试的时候,常常会问数组和链表的区别,很多人都回答说,“链表适合插入、删除,时间复杂度 O(1);数组适合查找,查找时间复杂度为 O(1)”。 实际上,这种表述是不准确的。数组是适合查找操作,但是查找的时间复杂度并不为 O(1)。即便是排好序的数组,你用二分查找,时间复杂度也是 O(logn)。 所以,正确的表述应该是,数组支持随机访问,根据下标随机访问的时间复杂度为 O(1)。

找一个bug就好比从一泡烂泥里找一条泥鳅,写一个bug就好比往一泡烂泥里丢一条泥鳅进去

数据结构在某种程度上和设计模式类似,都是前辈的武功套路。不同的是,设计模式是近几十年的卓越程序员的智慧结晶,而数据结构是几百上千年的无数科学家、数学家的智慧沉淀,更加具有深厚的背景。

18年元旦立下的flag要集中突击一下了.....

人生是一场马拉松,起跑的优劣对于整段路途而言并没有那么重要,笑到最后的都是一直在跑的人,也就是一辈子都在学习的人。

角色是谁并不重要,重要的是会不会抢戏~

Copyright © 2016 - 2018 Cion.
All Rights Reserved.
备案:鲁ICP备16007319号.