Golang JSON omitempty with time.Champ De Temps
essayer de JSON Marshal une structure qui contient 2 champs de temps. Mais je veux que le champ passe seulement s'il a une valeur temporelle. Donc je suis en utilisant json:",omitempty"
mais ça ne fonctionne pas.
Que puis-je définir la valeur de Date à so json.Marshal va le traiter comme une valeur vide (zéro) et ne pas l'inclure dans la chaîne json?
aire de jeux:http://play.golang.org/p/QJwh7yBJlo
Résultat Réel:
{"Timestamp": "2015-09-18T00:00: 00Z","Date":"0001-01-01T00:00: 00Z"}
Résultat Souhaité:
{"Timestamp":"2015-09-18T00:00: 00Z"}
Code:
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))
}
2 réponses
omitempty
l'option de balise ne fonctionne pas avec time.Time
c'est un struct
. Il y a une valeur "zéro" pour les structures, mais c'est une valeur de structure où tous les champs ont leur valeur zéro. C'est une valeur" valide", donc elle n'est pas traitée comme"vide".
mais en le changeant simplement en pointeur:*time.Time
, il va travailler (nil
les pointeurs sont traités comme" vides " pour le JSON marshaling/unmarshaling). Donc pas besoin d'écrire personnalisé Marshaler
dans ce cas:
type MyStruct struct {
Timestamp *time.Time `json:",omitempty"`
Date *time.Time `json:",omitempty"`
Field string `json:",omitempty"`
}
Utilisation:
ts := time.Date(2015, 9, 18, 0, 0, 0, 0, time.UTC)
ms := MyStruct{
Timestamp: &ts,
Field: "",
}
Sortie (comme souhaité):
{"Timestamp":"2015-09-18T00:00:00Z"}
sur le Jeux.
si vous ne pouvez pas ou ne voulez pas le changer en un pointeur, vous pouvez quand même réaliser ce que vous voulez en implémentant un custom Marshaler
et Unmarshaler
. Si vous le faites, vous pouvez utiliser le Time.IsZero()
méthode pour décider si un time.Time
la valeur est la valeur zéro.
vous pouvez définir vous-même le type de temps pour le format custom marshal, et l'utiliser partout à la place 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)
}