目錄
一 前言
- golang的強制類型轉換可以讓人抓狂,遇上json序列化/反序列化時候的時間類型參數,需要不斷的轉換參數類型,簡直讓人抓狂。
- 本文通過組合方式對時間類型進行拓展,並實現序列化/反序列化接口來解決時間json傳遞類型轉換問題。
二 實現
- 自定義jsonTime,時間格式以"2006-01-02 15:04:05" 爲例
const (
YYYYMMDDHHMISS = "2006-01-02 15:04:05" //常規類型
)
type JSONTime struct {
time.Time
}
- 實現序列化接口。(將時間轉化爲"2006-01-02 15:04:05"格式)
// MarshalJSON on JSONTime format Time field with %Y-%m-%d %H:%M:%S
func (t JSONTime) MarshalJSON() ([]byte, error) {
formatted := fmt.Sprintf("\"%s\"", t.Format(YYYYMMDDHHMISS))
return []byte(formatted), nil
}
// Value insert timestamp into mysql need this function.
func (t JSONTime) Value() (driver.Value, error) {
var zeroTime time.Time
if t.Time.UnixNano() == zeroTime.UnixNano() {
return nil, nil
}
return t.Time, nil
}
// Scan valueof time.Time
func (t *JSONTime) Scan(v interface{}) error {
value, ok := v.(time.Time)
if ok {
*t = JSONTime{Time: value}
return nil
}
return fmt.Errorf("can not convert %v to timestamp", v)
}
- 實現反序列化接口(將時間"2006-01-02 15:04:05"格式轉化爲時間)
// UnmarshalJSON implements the json.Unmarshaler interface.
// The time is expected to be a quoted string in RFC 3339 format.
func (t *JSONTime) UnmarshalJSON(data []byte) error {
// Ignore null, like in the main JSON package.
if string(data) == "null" {
return nil
}
// Fractional seconds are handled implicitly by Parse.
var err error
(*t).Time, err = time.ParseInLocation(`"`+YYYYMMDDHHMISS+`"`, string(data), time.Local)
return err
}
三 驗證
- 測試代碼
package util
import (
"encoding/json"
"fmt"
"testing"
"time"
)
type TestTime struct {
Time JSONTime `json:"time"`
Name string `json:"name"`
}
//格式化輸出
func (t *TestTime) ToString() string {
return fmt.Sprintf("time:%+v,name:%+v", t.Time, t.Name)
}
func TestJsonMarshal(t *testing.T) {
//測試序列化
testMarshal := &TestTime{
Time: JSONTime{time.Now()},
Name: "序列化",
}
marshal, err := json.Marshal(testMarshal)
if err != nil {
fmt.Print(err.Error())
}
fmt.Println("序列化字符串:",string(marshal))
//測試反序列化
src := []byte(`{"time":"2020-05-26 20:20:44","name":"反序列化"}`)
var testUnMarshal TestTime
err = json.Unmarshal(src, &testUnMarshal)
if err != nil {
fmt.Print(err.Error())
}
fmt.Println("反序列化結構體:",testUnMarshal.ToString())
}
- 結果驗證
=== RUN TestJsonMarshal
序列化字符串: {"time":"2020-05-26 20:30:53","name":"序列化"}
反序列化結構體: time:2020-05-26 20:20:44 +0800 CST,name:反序列化
--- PASS: TestJsonMarshal (0.00s)
PASS
四 總結
組合加實現接口是golang常用的擴展類的方式,由此可拓展出各種各種類型的數據參數序列化。
例如:golang實現mysql json數據類型的封裝,等。