Golang JSON omitempty With time.Time Field

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

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) } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!