随时间。时间字段

尝试 json Marshall 一个包含2个时间字段的结构。但是我只希望字段在有时间值的情况下通过。所以我使用 json:",omitempty",但它不工作。

我可以将 Date 值设置为什么。Marshall 会把它当作一个空(零)值,而不把它包含在 json 字符串中吗?

操场: http://play.golang.org/p/QJwh7yBJlo

实际成果:

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

预期结果:

{“时间戳”: “2015-09-18 T00: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))
}
31332 次浏览

您可以为自定义封送格式定义自定义 Time 类型,并在任何地方使用它来代替 time.Time

Https://play.golang.org/p/c8nir1uzaok

package main


import (
"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)
}

omitempty标记选项不适用于 time.Time,因为它是 struct。对于 struct,有一个“零”值,但是这是一个 struct 值,其中所有字段都有它们的零值。这是一个“有效”值,因此它不被视为“空”。

但是通过简单地将其更改为指针: *time.Time,它就可以工作(对于 json 封送处理/解封送处理,nil指针被视为“空的”)。所以在这种情况下不需要编写定制的 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"}

去游乐场试试。

如果不能或不想将其更改为指针,仍然可以通过实现自定义 MarshalerUnmarshaler来实现所需的内容。如果这样做,可以使用 Time.IsZero()方法确定 time.Time值是否为零值。

作为对 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 的情况有两个时间域,这会使它更加复杂。(你必须检查两者都没有,或者都是空的!)

可能有更好的方法来实现这一点,因此欢迎提出意见。