golang 使用gorequest 遇到的序列化的坑

    golang 序列化的庫沒其餘語言那麼好用,而後就掉坑裏了。git

    是用gorequest 庫發現的,這個高start 的庫,仍是有些問題。我使用場景是這樣的:github

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。至關因而數據被四捨五入了,一番追查,發現底層作了這個操做,把數據給變了:golang

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

    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。app

    給個正確的例子,應該使用UseNumber 反序列化:post

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)

}
相關文章
相關標籤/搜索