dt3674
2015-09-18 04:20
浏览 528

Golang JSON omitempty带有time.Time字段

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

图片转代码服务由CSDN问答提供 功能建议

试图对包含2个时间字段的结构进行JSON编组。 但我只希望该字段具有时间值才能通过。 所以我正在使用 json:“,omitempty” ,但是它不起作用。

我该如何将Date值设置为json.Marshal会像对待它一样 一个空(零)值,并且不包含在json字符串中?

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

实际结果: < blockquote>

{“ Timestamp”:“ 2015-09-18T00:00:00Z”,“ Date”:“ 0001-01-01T00:00:00Z”}

所需结果:

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

代码:

 包main 
 
import(
”  encoding / json“ 
” fmt“ 
” time“ 
)
 
type MyStruct struct {
时间戳记时间。时间`json:”,omitempty“`
日期时间。时间`json:”,omitempty  “`
字段字符串`json:”,omitempty“`
} 
 
func main(){
 ms:= MyStruct {
时间戳:time.Date(2015,9,18,0,0,  0,0,time.UTC),
 Fie  ld:“”,
} 
 
 bb,err:= json.Marshal(ms)
 if err!= nil {
 panic(err)
} 
 fmt.Println(string(bb)  )
} 
   
 
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • douwen6274 2015-09-18 07:17
    已采纳

    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.

    已采纳该答案
    打赏 评论
  • douju1280 2015-09-18 05:17

    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)
    }
    
    打赏 评论

相关推荐 更多相似问题