J'ai créé une API dans Go qui, une fois appelée, exécute une requête, crée une instance d'une structure, puis encode cette structure en JSON avant de la renvoyer à l'appelant. Je voudrais maintenant permettre à l'appelant d'être en mesure de sélectionner les champs spécifiques qu'ils aimeraient retourner en passant un paramètre GET "champs".
Cela signifie qu'en fonction de la ou des valeurs des champs, ma structure changerait. Existe-t-il un moyen de supprimer des champs d'une structure? Ou du moins les cacher dans la réponse JSON de manière dynamique? (Remarque: parfois, j'ai des valeurs vides, donc la balise JSON omitEmpty ne fonctionnera pas ici) Si aucun de ces éléments n'est possible, existe-t-il une suggestion sur une meilleure façon de gérer cela? Merci d'avance.
Une version plus petite des structures que j'utilise est ci-dessous:
type SearchResult struct {
Date string `json:"date"`
IdCompany int `json:"idCompany"`
Company string `json:"company"`
IdIndustry interface{} `json:"idIndustry"`
Industry string `json:"industry"`
IdContinent interface{} `json:"idContinent"`
Continent string `json:"continent"`
IdCountry interface{} `json:"idCountry"`
Country string `json:"country"`
IdState interface{} `json:"idState"`
State string `json:"state"`
IdCity interface{} `json:"idCity"`
City string `json:"city"`
} //SearchResult
type SearchResults struct {
NumberResults int `json:"numberResults"`
Results []SearchResult `json:"results"`
} //type SearchResults
J'encode et sort ensuite la réponse comme ceci:
err := json.NewEncoder(c.ResponseWriter).Encode(&msg)
Réponses:
EDIT: J'ai remarqué quelques votes négatifs et j'ai jeté un autre regard sur ce Q&A. La plupart des gens semblent manquer que le PO ait demandé que les champs soient sélectionnés dynamiquement en fonction de la liste de champs fournie par l'appelant. Vous ne pouvez pas faire cela avec la balise struct json définie statiquement.
Si vous voulez toujours ignorer un champ à encoder json, utilisez bien sûr
json:"-"
pour ignorer le champ (notez également que cela n'est pas nécessaire si votre champ n'est pas exporté - ces champs sont toujours ignorés par l'encodeur json). Mais ce n'est pas la question du PO.Pour citer le commentaire sur la
json:"-"
réponse:J'utiliserais une interface map [string] {} au lieu d'une structure dans ce cas. Vous pouvez facilement supprimer des champs en appelant la fonction
delete
intégrée sur la carte pour les champs à supprimer.Autrement dit, si vous ne pouvez pas interroger uniquement les champs demandés en premier lieu.
la source
map[string]interface{}
sens, mais cela ne nécessite pas que vous jetiez votre définition de type.Id
mais, je ne veux pas retourner la structure json entière. Merci pour cela!utilisez `json:" - "`
doc: http://golang.org/pkg/encoding/json/#Marshal
la source
Une autre façon de faire est d'avoir une structure de pointeurs avec la
,omitempty
balise. Si les pointeurs sont nuls , les champs ne seront pas Marshallés.Cette méthode ne nécessitera pas de réflexion supplémentaire ou une utilisation inefficace des cartes.
Même exemple que jorelli utilisant cette méthode: http://play.golang.org/p/JJNa0m2_nw
la source
Vous pouvez utiliser le
reflect
package pour sélectionner les champs souhaités en réfléchissant sur les balises de champ et en sélectionnant lesjson
valeurs de balise. Définissez une méthode sur votre type SearchResults qui sélectionne les champs souhaités et les renvoie en tant quemap[string]interface{}
, puis marshalez cela au lieu de la structure SearchResults elle-même. Voici un exemple de la façon dont vous pourriez définir cette méthode:et voici une solution exécutable qui montre comment vous appelleriez cette méthode et organiseriez votre sélection: http://play.golang.org/p/1K9xjQRnO8
la source
Je viens de publier sheriff , qui transforme les structures en une carte basée sur des balises annotées sur les champs de structure. Vous pouvez ensuite marshaler (JSON ou autres) la carte générée. Cela ne vous permet probablement pas de sérialiser uniquement l'ensemble des champs demandés par l'appelant, mais j'imagine que l'utilisation d'un ensemble de groupes vous permettrait de couvrir la plupart des cas. L'utilisation directe de groupes au lieu des champs augmenterait probablement également la capacité du cache.
Exemple:
la source
Prenez trois ingrédients:
Le
reflect
package à boucler sur tous les champs d'une structure.Une
if
déclaration pour sélectionner les champs que vous souhaitezMarshal
, etLe
encoding/json
forfait auxMarshal
domaines de votre goût.Préparation:
Mélangez-les dans une bonne proportion. Utilisez
reflect.TypeOf(your_struct).Field(i).Name()
pour obtenir un nom dui
e champ deyour_struct
.Utilisez
reflect.ValueOf(your_struct).Field(i)
pour obtenir uneValue
représentation de type d'uni
e champ deyour_struct
.Utilisez
fieldValue.Interface()
pour récupérer la valeur réelle (remontée vers le type interface {})fieldValue
du type deValue
(notez l'utilisation des crochets - la méthode Interface () produitinterface{}
Si vous parvenez heureusement à ne pas brûler de transistors ou de disjoncteurs dans le processus, vous devriez obtenir quelque chose comme ceci:
Portion:
servir avec une structure arbitraire et un
map[string]bool
des champs que vous souhaitez inclure, par exempleBon appétit!
la source
Vous pouvez utiliser l'attribut de balisage "omitifempty" ou créer des champs optionnels pointeurs et laisser ceux que vous voulez ignorer non initialisés.
la source
J'ai également rencontré ce problème, au début je voulais juste spécialiser les réponses dans mon gestionnaire http. Ma première approche consistait à créer un package qui copie les informations d'une structure dans une autre structure, puis à marshaler cette seconde structure. J'ai fait ce package en utilisant la réflexion, donc, je n'ai jamais aimé cette approche et je n'étais pas non plus dynamique.
J'ai donc décidé de modifier le package encoding / json pour ce faire. Les fonctions
Marshal
,MarshalIndent
et(Encoder) Encode
reçoit en outre untype F map[string]F
Je voulais simuler un JSON des champs nécessaires pour marshaler, donc il ne rassemble que les champs qui sont dans la carte.
https://github.com/JuanTorr/jsont
la source
La question est maintenant un peu ancienne, mais je suis tombé sur le même problème il y a quelque temps, et comme je ne trouvais pas de moyen facile de le faire, j'ai construit une bibliothèque remplissant cet objectif. Il permet de générer facilement un à
map[string]interface{}
partir d'une structure statique.https://github.com/tuvistavie/structomap
la source
[]byte
est qu'il n'est pas très réutilisable: pas de moyen facile d'ajouter un champ par la suite, par exemple. Je suggérerais donc de créer unmap[string]interface{}
et de laisser la partie de sérialisation JSON dans la bibliothèque standard.Je n'ai pas eu le même problème mais similaire. Le code ci-dessous résout également votre problème, bien sûr si le problème de performances ne vous dérange pas. Avant d'implémenter ce type de solution dans votre système, je vous recommande de repenser votre structure si vous le pouvez. Envoyer une réponse de structure variable est une sur-ingénierie. Je crois qu'une structure de réponse représente un contrat entre une demande et une ressource et qu'elle ne devrait pas dépendre des demandes (vous pouvez rendre les champs indésirables nuls, je le fais). Dans certains cas, nous devons implémenter cette conception, si vous pensez que vous êtes dans ce cas, voici le lien de lecture et le code que j'utilise.
la source
J'ai créé cette fonction pour convertir une structure en chaîne JSON en ignorant certains champs. J'espère que cela aidera.
Exemple: https://play.golang.org/p/nmq7MFF47Gp
la source