2015-09-18 11 views
10

2つの時間フィールドを含む構造体をjsonにマーシャリングしようとしています。しかし、私は時間価値がある場合にだけフィールドが来るようにしたい。だから私はjson:",omitempty"を使用していますが、動作していません。Golang JSON omitempty with time.Timeフィールド

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

この機能は[time.Timeで動作しません](https://github.com/golang/go/blob/1fd78e1f600d10475b85381427bda9f14f86e0f0/src/encoding/json/encode.go#L278-L294)。 –

+1

おそらく最も簡単な方法は、MyStructにhttp://golang.org/pkg/encoding/json/#Unmarshalerを実装させることです。 – Volker

+0

よく知っていると良いアドバイス。ありがとう! –

答えて

26

omitemptyタグオプションはであるため、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上でそれを試してみてください。

ポインタに変更できない場合や、ポインタに変更したくない場合は、カスタムMarshalerUnmarshalerを実装することで、目的を達成できます。そうする場合は、Time.IsZero()メソッドを使用して、time.Timeの値がゼロ値であるかどうかを判断できます。

+0

それは素晴らしい答えです。ありがとう! –

2

は、あなたがあなた自身を定義することができ、カスタムマーシャル・フォーマットのための時間タイプ、および使用どこでも代わりに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) 
}