J'ai une structure comme celle-ci:
type Result struct {
Data MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}
Mais même si l'instance de MyStruct est entièrement vide (ce qui signifie que toutes les valeurs sont par défaut), elle est sérialisée comme:
"data":{}
Je sais que les documents encoding / json spécifient que les champs «vides» sont:
false, 0, tout pointeur ou valeur d'interface nil, et tout tableau, tranche, carte ou chaîne de longueur zéro
mais sans considération pour une structure avec toutes les valeurs vides / par défaut. Tous ses champs sont également étiquetés omitempty
, mais cela n'a aucun effet.
Comment puis-je obtenir le package JSON pour ne pas marshaler mon champ qui est une structure vide?
&MyStruct{ /* values */ }
compte comme un pointeur nul? La valeur n'est pas nulle.Comme @chakrit mentionné dans un commentaire, vous ne pouvez pas obtenir ce travail en mettant en place
json.Marshaler
surMyStruct
et la mise en œuvre d' une fonction de rassemblement JSON personnalisé sur chaque struct qui l' utilise peut être beaucoup plus de travail. Cela dépend vraiment de votre cas d'utilisation pour savoir si cela vaut le travail supplémentaire ou si vous êtes prêt à vivre avec des structures vides dans votre JSON, mais voici le modèle que j'utilise appliqué àResult
:type Result struct { Data MyStruct Status string Reason string } func (r Result) MarshalJSON() ([]byte, error) { return json.Marshal(struct { Data *MyStruct `json:"data,omitempty"` Status string `json:"status,omitempty"` Reason string `json:"reason,omitempty"` }{ Data: &r.Data, Status: r.Status, Reason: r.Reason, }) } func (r *Result) UnmarshalJSON(b []byte) error { decoded := new(struct { Data *MyStruct `json:"data,omitempty"` Status string `json:"status,omitempty"` Reason string `json:"reason,omitempty"` }) err := json.Unmarshal(b, decoded) if err == nil { r.Data = decoded.Data r.Status = decoded.Status r.Reason = decoded.Reason } return err }
Si vous avez d'énormes structures avec de nombreux champs, cela peut devenir fastidieux, en particulier en changeant l'implémentation d'une structure plus tard, mais à moins de réécrire l'ensemble du
json
package pour répondre à vos besoins (ce n'est pas une bonne idée), c'est à peu près la seule façon dont je peux penser à obtenir ceci fait tout en gardant un non-pointeurMyStruct
là - dedans.De plus, vous n'avez pas besoin d'utiliser des structures en ligne, vous pouvez en créer des nommées. J'utilise LiteIDE avec la complétion de code, donc je préfère en ligne pour éviter l'encombrement.
la source
Data
est une structure initialisée, elle n'est donc pas considérée comme vide car elleencoding/json
ne regarde que la valeur immédiate, pas les champs à l'intérieur de la structure.Malheureusement, le retour
nil
dejson.Marhsler
ne fonctionne pas actuellement:func (_ MyStruct) MarshalJSON() ([]byte, error) { if empty { return nil, nil // unexpected end of JSON input } // ... }
Vous pouvez également donner
Result
un marshaleur, mais cela n'en vaut pas la peine.La seule option, comme le suggère Matt, est de créer
Data
un pointeur et de définir la valeur surnil
.la source
encoding/json
peux pas vérifier les champs enfants de la structure. Ce ne serait pas très efficace, oui. Mais ce n'est certainement pas impossible.json.Marshaler
cas par cas.MyStruct
est vide ou non en implémentant unjson.Marshaler
surMyStruct
lui-même. Preuve: play.golang.org/p/UEC8A3JGvxjson.Marshaler
sur leResult
type conteneur lui-même, ce qui pourrait être très gênant.Il existe une proposition exceptionnelle de Golang pour cette fonctionnalité qui est active depuis plus de 4 ans, donc à ce stade, il est prudent de supposer qu'elle ne sera pas intégrée à la bibliothèque standard de si tôt. Comme @Matt l'a souligné, l' approche traditionnelle consiste à convertir les structures en pointeurs vers les structures . Si cette approche est irréalisable (ou peu pratique), une alternative consiste à utiliser un autre encodeur json qui prend en charge l' omission de structures à valeur nulle .
J'ai créé un miroir de la bibliothèque Golang json ( clarketm / json ) avec un support supplémentaire pour omettre les structures à valeur nulle lorsque la
omitempty
balise est appliquée. Cette bibliothèque détecte l' absence de zéron d'une manière similaire au populaire encodeur YAML go-yaml en vérifiant récursivement les champs de structure publique .par exemple
$ go get -u "github.com/clarketm/json"
import ( "fmt" "github.com/clarketm/json" // drop-in replacement for `encoding/json` ) type Result struct { Data MyStruct `json:"data,omitempty"` Status string `json:"status,omitempty"` Reason string `json:"reason,omitempty"` } j, _ := json.Marshal(&Result{ Status: "204", Reason: "No Content", }) fmt.Println(string(j))
// Note: `data` is omitted from the resultant json. { "status": "204" "reason": "No Content" }
la source