3 回答
TA贡献1906条经验 获得超10个赞
该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值是否为零值。
TA贡献1802条经验 获得超6个赞
您可以为自定义元帅格式定义自己的时间类型,并在任何地方使用它 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)
}
TA贡献1856条经验 获得超5个赞
作为 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 案例有两个时间字段,这会使它变得更加复杂。(你必须检查两者都不是,两者都是空的!)
可能有更好的方法来实现这一点,所以欢迎提出意见。
- 3 回答
- 0 关注
- 226 浏览
添加回答
举报