JSON omitempty with time.Time 字段

尝试对包含 2 个时间字段的结构进行 json 编组。但我只希望该字段具有时间价值。所以我正在使用json:",omitempty"但它不起作用。


我可以将 Date 值设置为什么,以便 json.Marshal 将其视为空(零)值而不将其包含在 json 字符串中?


游乐场:http : //play.golang.org/p/QJwh7yBJlo


实际结果:


{"时间戳":"2015-09-18T00:00:00Z","日期":"0001-01-01T00:00:00Z"}


期望的结果:


{"时间戳":"2015-09-18T00:00:00Z"}


代码:


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

}


30秒到达战场
浏览 227回答 3
3回答

隔江千里

该omitempty标签选项不能正常工作time.Time,因为它是一个struct。结构体有一个“零”值,但这是一个结构体值,其中所有字段的值都为零。这是一个“有效”值,因此不被视为“空”。但是通过简单地将其更改为指针:*time.Time,它将起作用(nil对于 json 编组/解组,指针被视为“空”)。所以Marshaler在这种情况下不需要编写自定义:type MyStruct struct {    Timestamp *time.Time `json:",omitempty"`    Date      *time.Time `json:",omitempty"`    Field     string     `json:",omitempty"`}使用它:ts := time.Date(2015, 9, 18, 0, 0, 0, 0, time.UTC)ms := MyStruct{    Timestamp: &ts,    Field:     "",}输出(根据需要):{"Timestamp":"2015-09-18T00:00:00Z"}在Go Playground上试一试。如果您不能或不想将其更改为指针,您仍然可以通过实现自定义Marshaler和Unmarshaler. 如果这样做,您可以使用该Time.IsZero()方法来确定某个time.Time值是否为零值。

呼啦一阵风

您可以为自定义元帅格式定义自己的时间类型,并在任何地方使用它 time.Timehttps://play.golang.org/p/C8nIR1uZAokpackage mainimport (    "bytes"    "encoding/json"    "fmt"    "time")type MyTime struct {    *time.Time}func (t MyTime) MarshalJSON() ([]byte, error) {    return []byte(t.Format("\"" + time.RFC3339 + "\"")), 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) {    // by convention, unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.    if bytes.Equal(data, []byte("null")) {        return nil    }    // Fractional seconds are handled implicitly by Parse.    tt, err := time.Parse("\""+time.RFC3339+"\"", 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)}

RISEBY

作为 icza 回答的后续,这里是一个自定义编组器,它省略了一个空的日期字段,但保持其余字段不变。func (ms *MyStruct) MarshalJSON() ([]byte, error) {    type Alias MyStruct    if ms.Timestamp.IsZero() {        return json.Marshal(&struct {            Timestamp int64 `json:",omitempty"`            *Alias        }{            Timestamp: 0,            Alias:     (*Alias)(ms),        })    } else {        return json.Marshal(&struct {            *Alias        }{            Alias: (*Alias)(ms),        })    }}这从http://choly.ca/post/go-json-marshalling/借用OPs 案例有两个时间字段,这会使它变得更加复杂。(你必须检查两者都不是,两者都是空的!)可能有更好的方法来实现这一点,所以欢迎提出意见。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go