可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Trying to json Marshal a struct that contains 2 time fields. But I only want the field to come through if it has a time value. So I'm using json:",omitempty" but it's not working.
What can I set the Date value to so json.Marshal will treat it like an empty (zero) value and not include it in the json string?
Playground: http://play.golang.org/p/QJwh7yBJlo
Actual Outcome:
{"Timestamp":"2015-09-18T00:00:00Z","Date":"0001-01-01T00:00:00Z"}
Desired Outcome:
{"Timestamp":"2015-09-18T00:00:00Z"}
Code:
package main import ( "encoding/json" "fmt" "time" ) type MyStruct struct { Timestamp time.Time `json:",omitempty"` Date time.Time `json:",omitempty"` Field string `json:",omitempty"` } func main() { ms := MyStruct{ Timestamp: time.Date(2015, 9, 18, 0, 0, 0, 0, time.UTC), Field: "", } bb, err := json.Marshal(ms) if err != nil { panic(err) } fmt.Println(string(bb)) }
回答1:
The omitempty tag option does not work with time.Time as it is a struct. There is a "zero" value for structs, but that is a struct value where all fields have their zero values. This is a "valid" value, so it is not treated as "empty".
But by simply changing it to a pointer: *time.Time, it will work (nil pointers are treated as "empty" for json marshaling/unmarshaling). So no need to write custom Marshaler in this case:
type MyStruct struct { Timestamp *time.Time `json:",omitempty"` Date *time.Time `json:",omitempty"` Field string `json:",omitempty"` }
Using it:
ts := time.Date(2015, 9, 18, 0, 0, 0, 0, time.UTC) ms := MyStruct{ Timestamp: &ts, Field: "", }
Output (as desired):
{"Timestamp":"2015-09-18T00:00:00Z"}
Try it on the Go Playground.
If you can't or don't want to change it to a pointer, you can still achieve what you want by implementing a custom Marshaler and Unmarshaler. If you do so, you can use the Time.IsZero() method to decide if a time.Time value is the zero value.
回答2:
you may define you self Time type for custom marshal format, and use it everywhere instead time.Time
http://play.golang.org/p/S9VIWNAaVS
package main import "fmt" import "time" import "encoding/json" type MyTime struct{ *time.Time } func (t MyTime) MarshalJSON() ([]byte, error) { return []byte(t.Format("\"2006-01-02T15:04:05Z\"")), nil } // UnmarshalJSON implements the json.Unmarshaler interface. // The time is expected to be a quoted string in RFC 3339 format. func (t *MyTime) UnmarshalJSON(data []byte) (err error) { // Fractional seconds are handled implicitly by Parse. tt, err := time.Parse("\"2006-01-02T15:04:05Z\"", string(data)) *t = MyTime{&tt} return } func main() { t := time.Now() d, err := json.Marshal(MyTime{&t}) fmt.Println(string(d), err) var mt MyTime json.Unmarshal(d, &mt) fmt.Println(mt) }