はじめに
Go 言語で構造体を JSON に変換すると time.Time
型の要素は RFC3339 フォーマットに変換されます。
これを他のフォーマットにしたくて
golang time json marshal
といったキーワードでググると time.Time
型を要素に持つ構造体 (jsonTime
) を定義して MarshalJSON()
メソッドを実装する、以下のような方法がヒットします。
type jsonTime struct {
time.Time
}
func (j jsonTime) MarshalJSON() ([]byte, error) {
return json.Marshal(j.Format("2006/01/02"))
}
これで解決なのですが、私にとっては jsonTime
が構造体だと都合が悪かったため、それを使わない方法を調べました。
環境
% go version
go version go1.17.1 darwin/amd64
実装方法
まずコードを示します。
package main
import (
"encoding/json"
"fmt"
"time"
)
type jsonTime time.Time
func (j jsonTime) MarshalJSON() ([]byte, error) {
t := time.Time(j)
return json.Marshal(t.Format("2006/01/02"))
}
type data struct {
Id int `json:"id"`
Name string `json:"name"`
CreatedAt jsonTime `json:"created_at"`
}
func main() {
d := data{
Id: 1,
Name: "Foo Bar",
CreatedAt: jsonTime(time.Now()),
}
bytes, _ := json.Marshal(d)
fmt.Printf("%s", bytes)
}
先述した jsonTime
構造体の代わりに、defined type を使用して time.Time
型から jsonTime
型を定義しています。
ポイントは MarshalJSON()
メソッドで jsonTime
型のレシーバを time.Time
型にキャストしているところです。
次に実行結果です。
{"id":1,"name":"Foo Bar","created_at":"2021/09/22"}
日付を任意のフォーマットにできました。
おわりに
私が探した限り、日付を任意のフォーマットの JSON に変換する方法はどれも同じものしか見つけられませんでした。
フォーマットのやり方にこそ差異はありましたが、構造体を使っていることは同じでした。
もしかして defined type では何か不都合があったりするのでしょうか?
それとも構造体以外も使えるのは当たり前すぎて誰も記事にしないだけ?