在这里描述了go使用自定义json序列化方法将时间类型time.Time序列化为时间戳的方法。没想到面对一个新的序列化需求转眼就忘了这个方法,所以这里再写一次。
本次遇到的问题是64位整数id序列化为字符串string。由于javascript中所有数字都是64位的浮点数,所以整数只能精确的表示53bit长的数字。我们使用雪花算法生成的id通常都是64位整数,所以后端给前端返回数据时,最好将id序列化成字符串。
package main_test
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"testing"
)
// 定义一个DbId类型,64位整型,改写json方法
type DbId int64
// 这里主要注意反序列化时需要去掉两边的引号
func (d *DbId) UnmarshalJSON(data []byte) (err error) {
s := strings.Trim(string(data), "\"")
intNum, err := strconv.ParseInt(s, 10, 64)
if err != nil {
return err
}
*d = DbId(intNum)
return
}
// 这里需要手动加上引号,不会自动生成
func (d *DbId) MarshalJSON() ([]byte, error) {
return ([]byte)("\"" + strconv.FormatInt(int64(*d), 10) + "\""), nil
}
// 使用我们自定义的DbId类型
type TestStruct struct {
Id1 DbId
Id2 DbId
Id3 DbId
}
// 作为对比,使用string类型
type TestStruct2 struct {
Id1 string
Id2 string
Id3 string
}
func TestChan(t *testing.T) {
testStruct := TestStruct{
Id1: 1234567890123,
Id2: 3456787901234,
Id3: 5678901234567,
}
resBytes, err := json.Marshal(&testStruct)
if err != nil {
t.Fatal(err)
}
// 看一下序列化的结果
fmt.Println(string(resBytes))
var testStruct12 TestStruct
err = json.Unmarshal(resBytes, &testStruct12)
if err != nil {
t.Fatal(err)
}
// 反序列化的结果
fmt.Printf("%v", testStruct12)
fmt.Println()
var testStruct2 TestStruct2
err = json.Unmarshal(resBytes, &testStruct2)
if err != nil {
t.Fatal(err)
}
// 这里可以看到确实是string,可以直接反序列化
fmt.Printf("%v", testStruct2)
}
网友评论