2015-09-18 13 views
10

Provando a json Marshal una struttura che contiene 2 campi di tempo. Ma voglio solo che il campo arrivi se ha un valore temporale. Quindi sto usando json:",omitempty" ma non funziona.Golang JSON omitempty Con time.Time Field

In che modo è possibile impostare il valore Date in modo che json.Marshal lo tratti come un valore vuoto (zero) e non lo includa nella stringa json?

Playground: http://play.golang.org/p/QJwh7yBJlo

Actual Risultato:

{ "Timestamp": "2015-09-18T00: 00: 00Z", "Data": "0001-01-01T00: 00: 00Z "}

Risultato desiderato:

{ "Timestamp": "2015-09-18T00: 00: 00Z"}

Codice:

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

La funzione [non funziona con time.Time] (https://github.com/golang/go/blob/1fd78e1f600d10475b85381427bda9f14f86e0f0/src/encoding/json/encode.go#L278-L294). –

+1

Probabilmente il modo più semplice per raggiungere il tuo obiettivo sarebbe quello di consentire a MyStruct di implementare http://golang.org/pkg/encoding/json/#Unmarshaler. – Volker

+0

Buono a sapersi e buon consiglio. Grazie! –

risposta

26

L'opzione di tag omitempty non funziona con time.Time in quanto è un struct. C'è un valore "zero" per le strutture, ma quello è un valore di struttura in cui tutti i campi hanno i loro valori zero. Questo è un valore "valido", quindi non viene considerato come "vuoto".

Ma semplicemente cambiandolo in un puntatore: *time.Time, funzionerà (nil i puntatori sono considerati come "vuoti" per json marshalling/unmarshaling). Quindi nessun bisogno di scrivere personalizzato Marshaler in questo caso:

type MyStruct struct { 
    Timestamp *time.Time `json:",omitempty"` 
    Date  *time.Time `json:",omitempty"` 
    Field  string  `json:",omitempty"` 
} 

Usandolo:

ts := time.Date(2015, 9, 18, 0, 0, 0, 0, time.UTC) 
ms := MyStruct{ 
    Timestamp: &ts, 
    Field:  "", 
} 

uscita (se lo desideri):

{"Timestamp":"2015-09-18T00:00:00Z"} 

Prova sul Go Playground.

Se non è possibile o non si desidera cambiarlo in un puntatore, è comunque possibile ottenere ciò che si desidera implementando una personalizzata Marshaler e Unmarshaler. In tal caso, è possibile utilizzare il metodo Time.IsZero() per decidere se un valore time.Time è il valore zero.

+0

Questa è un'ottima risposta. Grazie! –

2

è possibile definire il tipo di auto che si Tempo per il formato maresciallo personalizzato, e l'uso ovunque invece 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) 
} 
Problemi correlati