前置き
構造体をJSONにする場合、encoding/json
のfunc Marshal(v interface{}) ([]byte, error)
を利用する。
package main
import (
"encoding/json"
"fmt"
"time"
)
type Data struct {
Id int `json:"id"`
Title string `json:"title"`
CreatedAt time.Time `json:"created_at"`
}
func main() {
loc, _ := time.LoadLocation("Asia/Tokyo")
d := Data{
1,
"HelloWorld",
time.Date(2014, 8, 25, 0, 0, 0, 0, loc),
}
bytes, _ := json.Marshal(d)
fmt.Printf("%s", bytes)
}
実行結果(本来は改行無し)
{
"id":1,
"title":"HelloWorld",
"created_at":"2014-08-25T00:00:00+09:00"
}
この場合、created_at
のフォーマットを2014-08-25T00:00:00+09:00
から2014-08-25
にしたいとする。
formatを設定する
JSONへMarshal()
が実行される場合、それぞれの型のMarshalJSON()
が実行される。
上の場合created_at
はTime
の関数であるfunc UnmarshalJSON()を利用している。
http://golang.org/src/pkg/time/time.go?s=27454:27507#L936
func (t *Time) UnmarshalJSON(data []byte) (err error) {
// Fractional seconds are handled implicitly by Parse.
*t, err = Parse(`"`+RFC3339+`"`, string(data))
return
}
つまりは、RFC3339
形式のstring型に変換している。
なので、新規にUnmarshalJSON()を持った構造体を新しく作成する必要がある。
// 独自のjsonTimeを作成
type jsonTime struct {
time.Time
}
// formatを設定
func (j jsonTime) format() string {
return j.Time.Format("2006-01-02")
}
// MarshalJSON() の実装
func (j jsonTime) MarshalJSON() ([]byte, error) {
return []byte(`"` + j.format() + `"`), nil
}
// CreatedAtの型をtime.TimeからjsonTimeに変更
type Data struct {
Id int `json:"id"`
Title string `json:"title"`
CreatedAt jsonTime `json:"created_at"`
}
func main() {
loc, _ := time.LoadLocation("Asia/Tokyo")
d := Data{
1,
"HelloWorld",
jsonTime{time.Date(2014, 8, 25, 0, 0, 0, 0, loc)},
}
bytes, _ := json.Marshal(d)
fmt.Printf("%s", bytes)
}
実行結果(改行は無し)
{
"id": 1,
"title": "HelloWorld",
"created_at": "2014-08-25"
}
まとめ
- JSONのMarshalをする場合、値の型の
UnmarshalJSON()
が使われる。 -
UnmarshalJSON()
を独自で実装するために新しい型を実装する必要がある。