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 關注
- 284 瀏覽
添加回答
舉報