应用背景:
前端的数字类型最大范围 为 2^-53 ~2^-53-1 ,后端int64 为 2^-63~ 2^63-1
如果后端传给前端的数据超过前端的取值返回那么这个数据便会失真,
所以后端可以先把这个数字转化为字符串再传给前端,当从前端接收到数据后再反序列化为数字
实例应用:有一个card结构体,有ID 和 Score属性这两个属性取值范围为2^-63~ 2^63-1, 实现在进行前后端数据交互时保证card里的ID和Score数据不失真。
实现json序列化(字符串与整形的序列化)
创建Card结构体
type Card struct {
ID int64 `json:"id,string"` // 添加string tag
Score float64 `json:"score,string"` // 添加string tag
}
创建结构体时需要在结构体成员属性后面加上tag(标签) 如 `json:"id,string"` 表示为json类型的tag tag名为id ,如果序列化将ID转化为 id 类型为string类型
go语言库封装的序列化函数
func Marshal(v any) ([]byte, error) {
e := newEncodeState()
err := e.marshal(v, encOpts{escapeHTML: true})
if err != nil {
return nil, err
}
buf := append([]byte(nil), e.Bytes()...)
encodeStatePool.Put(e)
return buf, nil
}
我们调用时只需要
package main
import (
"encoding/json"
"fmt"
)
type Card struct {
ID int64 `json:"id,string"` // 添加string tag
Score float64 `json:"score,string"` // 添加string tag
}
func main() {
code := Card{1, 12.0}
marshal, _ := json.Marshal(code)
fmt.Println(string(marshal))//{"id":"1","score":"12"} 序列化时,key变tag值 int64 float64被序列化为string
jsonStr1 := `{"id":"1234456","score":"88.50"}`
var c1 Card
if err := json.Unmarshal([]byte(jsonStr1), &c1); err != nil {
fmt.Printf("json.Unmarsha jsonStr1 failed, err:%v\n", err)
return
}
fmt.Printf("c1:%#v\n", c1) // c1:main.Card{ID:1234567, Score:88.5}
//反序列化时key为字段值 string被反序列化为 int64 float64
fmt.Printf("c1.ID:%T\n", c1.ID)
} //#可以输出c1
总结
本例将 code{1,12.0} 序列化为josn格式 {"id":"1","score":"12"}
`{"id":"1234456","score":"88.50"}`反序列化为Card{ID:1234567, Score:88.5}
序列化时将结构体变量名转化为tag名 类型转化为tag的类型
反序列化时将tag名转化为结构体变量名 类型转化为结构体变量的类型