Maison > développement back-end > Golang > le corps du texte

Comment faire la différence entre les champs vides et les champs non définis lors de l'utilisation de JSON dans Golang

藏色散人
Libérer: 2020-09-09 09:37:29
avant
2934 Les gens l'ont consulté
Vous trouverez ci-dessous

Tutoriel Comment faire la différence entre les champs vides et les champs non définis lors de lutilisation de JSON dans Golanglang colonne pour présenter la méthode d'utilisation des partitions de temps JSON et l'impossibilité de configurer les champs dans Comment faire la différence entre les champs vides et les champs non définis lors de lutilisation de JSON dans Golanglang. J'espère que cela sera utile aux amis. besoin!

Comment faire la différence entre les champs vides et les champs non définis lors de lutilisation de JSON dans Golang

Il y a quelques semaines, je travaillais sur un microservice Comment faire la différence entre les champs vides et les champs non définis lors de lutilisation de JSON dans Golanglang et j'avais besoin d'ajouter la prise en charge des opérations CURP à l'aide de données JSON. Généralement, je créais une structure pour l'entité. Tous les champs et l'attribut 'omitempty' sont définis dans le corps, comme indiqué ci-dessous

type Article struct {
   Id   string      `json:"id"`
   Name string      `json:"name,omitempty"`
   Desc string      `json:"desc,omitempty"`
}
Copier après la connexion

Problèmes

Mais cette représentation pose de sérieux problèmes, notamment pour les opérations de mise à jour ou d'édition .

Par exemple, supposons que les données JSON de la demande de mise à jour ressemblent à ceci

{"id":"1234","name":"xyz","desc":""}
Copier après la connexion

Notez le champ desc vide. Examinons maintenant les données de la demande dans À quoi ressemblent-elles après. déblocage dans Comment faire la différence entre les champs vides et les champs non définis lors de lutilisation de JSON dans Golang

func Test_JSON1(t *testing.T) {         
   jsonData:=`{"id":"1234","name":"xyz","desc":""}`
   req:=Article{}
   _=json.Unmarshal([]byte(jsonData),&req)
   fmt.Printf("%+v",req)
}Output:
=== RUN   Test_JSON1
{Id:1234 Name:xyz Desc:}
Copier après la connexion

La description ici est une chaîne vide. Évidemment, le client souhaite définir desc sur une chaîne vide, ce qui est déduit par notre programme.

Cependant, si le client ne le fait pas. souhaitez modifier la valeur existante de Desc, dans ce cas, il est incorrect d'envoyer à nouveau une chaîne de description, donc les données JSON demandées peuvent ressembler à ceci

{"id":"1234","name": "xyz">

Nous le décompressons dans notre structure

func Test_JSON2(t *testing.T) {         
   jsonData:=`{"id":"1234","name":"xyz"}`
   req:=Article{}
   _=json.Unmarshal([]byte(jsonData),&req)
   fmt.Printf("%+v",req)
}Output:
=== RUN   Test_JSON2
{Id:1234 Name:xyz Desc:}
Copier après la connexion

Eh bien, Desc sera toujours obtenu sous forme de chaîne vide, alors comment faire la distinction entre les champs non définis et les champs vides

réponse courte ? Pointeur

la solution

est soumise à certaines bibliothèques Comment faire la différence entre les champs vides et les champs non définis lors de lutilisation de JSON dans Golanglang existantes inspirées, telles que

go-github. Nous pouvons changer les champs de structure en types de pointeur comme indiqué ci-dessous

type Article struct {
   Id    string      `json:"id"`
   Name *string      `json:"name,omitempty"`
   Desc *string      `json:"desc,omitempty"`
}
Copier après la connexion

En faisant cela, nous ajoutons un statut supplémentaire Si le champ n'existe pas dans le JSON d'origine, le champ de structure sera vide (<🎜). >

nil).En revanche, si le champ existe et est nul, alors le pointeur n'est pas nul et le champ contient une valeur nulle.

Remarque

- Je n'ai pas modifié le champ 'Id' en un type de pointeur car il n'a pas de statut vide et l'identifiant est requis, similaire à l'identifiant dans le base de données.Essayons à nouveau.

func Test_JSON_Empty(t *testing.T) {
   jsonData := `{"id":"1234","name":"xyz","desc":""}`
   req := Article{}
   _ = json.Unmarshal([]byte(jsonData), &req)
   fmt.Printf("%+v\n", req)
   fmt.Printf("%s\n", *req.Name)
   fmt.Printf("%s\n", *req.Desc)
}
func Test_JSON_Nil(t *testing.T) {
   jsonData := `{"id":"1234","name":"xyz"}`
   req := Article{}
   _ = json.Unmarshal([]byte(jsonData), &req)
   fmt.Printf("%+v\n", req)
   fmt.Printf("%s\n", *req.Name)
}
Copier après la connexion

Output

=== RUN   Test_JSON_Empty
{Id:1234 Name:0xc000088540 Desc:0xc000088550}
Name: xyz
Desc: 
--- PASS: Test_JSON_Empty (0.00s)=== RUN   Test_JSON_Nil
{Id:1234 Name:0xc00005c590 Desc:<nil>}
Name: xyz
--- PASS: Test_JSON_Nil (0.00s)
Copier après la connexion

Le premier cas, puisque desc est défini sur une chaîne vide, nous obtenons un pointeur non nul dans
Desc

et contient la valeur d'une chaîne vide. Dans le second cas, le champ n'est pas défini, et on obtient un pointeur de chaîne de caractère nul.

On peut donc distinguer. entre deux mises à jour. Cette méthode s'applique non seulement aux chaînes, mais également à tous les autres types de données, y compris les entiers, les structures imbriquées, etc.

Mais cette approche pose quelques problèmes.

Sécurité nulle

 : Les types de données sans pointeur sont intrinsèquement sûrs pour les valeurs nulles. Dans Comment faire la différence entre les champs vides et les champs non définis lors de lutilisation de JSON dans Golanglang, cela signifie que les chaînes ou les entiers ne peuvent jamais être nuls. Mais si des pointeurs sont définis, ces types de données sont par défaut nuls. défini manuellement. Par conséquent, les tentatives d'accès à ces pointeurs sans vérifier les données de nullité peuvent provoquer le blocage de l'application.

# 以下代码将崩溃, 因为 desc 为空
func Test_JSON_Nil(t *testing.T) {
   jsonData := `{"id":"1234","name":"xyz"}`
   req := Article{}
   _ = json.Unmarshal([]byte(jsonData), &req)
   fmt.Printf("%+v\n", req)
   fmt.Printf("%s\n", *req.Desc)
}
Copier après la connexion
Ce problème peut être facilement résolu en recherchant toujours un pointeur nul, mais votre code peut paraître verbeux.

Oui Imprimabilité

 : Comme vous l'avez peut-être remarqué dans la sortie des solutions basées sur un pointeur, la valeur du pointeur n'est pas imprimée. Vingt imprime la valeur hexadécimale du pointeur, ce qui est peu. utilisation dans l'application . Cela peut également être surmonté en réutilisant l'interface stringer.

func (a *Article) String() string {
   output:=fmt.Sprintf("Id: %s ",a.Id)
   if a.Name!=nil{
   output+=fmt.Sprintf("Name: &#39;%s&#39; ",*a.Name)
   }
   if u.Desc!=nil{
   output+=fmt.Sprintf("Desc: &#39;%s&#39; ",u.Desc)
   }
   return output
}
Copier après la connexion

Annexe

 :

Une autre façon de résoudre le problème ci-dessus est utiliser nullable Une bibliothèque tierce de types dont les types peuvent fournir des méthodes pour vérifier s'ils sont nuls sans se soucier des pointeurs.
  • github.com/guregu/null
  • github.com/google /go-github
Adresse originale : https://medium.com/@arpitkh96/différentiate-between-empty-and-not-set-fields-with-json-in- golang-957bb2c5c065

Adresse de traduction : https://learnku.com/go/t/49332

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:learnku.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal