web-dev-qa-db-fra.com

Golang JSON omitempty With time.Time Field

Essayer de json Marshal une structure qui contient 2 champs de temps. Mais je veux que le champ ne passe que s'il a une valeur de temps. J'utilise donc json:",omitempty" mais ça ne marche pas.

Que puis-je définir pour que la valeur Date soit json.Marshal la traitera comme une valeur vide (zéro) et ne l'inclura pas dans la chaîne json?

Aire de jeux: http://play.golang.org/p/QJwh7yBJlo

Résultat réel:

{"Horodatage": "2015-09-18T00: 00: 00Z", "Date": "0001-01-01T00: 00: 00Z"}

Résultat souhaité:

{"Horodatage": "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))
}
31
Joe Bergevin

L'option de balise omitempty ne fonctionne pas avec time.Time Car 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 leurs valeurs nulles. Il s'agit d'une valeur "valide", elle n'est donc pas traitée comme "vide".

Mais en le changeant simplement en un pointeur: *time.Time, Cela fonctionnera (nil les pointeurs sont traités comme "vides" pour 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"`
}

En l'utilisant:

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"}

Essayez-le sur le Go Playground .

Si vous ne pouvez pas ou ne voulez pas le changer en pointeur, vous pouvez toujours obtenir ce que vous voulez en implémentant un Marshaler et Unmarshaler . Si vous le faites, vous pouvez utiliser la méthode Time.IsZero() pour décider si une valeur time.Time Est la valeur zéro.

62
icza

vous pouvez définir votre propre type d'heure pour le format de marshal personnalisé 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
Jiang YD