go自定义int64序列化为string

2020-09-15  本文已影响0人  猫尾草

在这里描述了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)
}

上一篇 下一篇

猜你喜欢

热点阅读