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))
}
17
demandé sur icza 2015-09-18 07:20:34

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.

41
répondu icza 2017-01-26 14:02:38

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)
}
2
répondu Jiang YD 2015-09-18 05:17:30