Comment utiliser correctement les struct tags JSON

GolangGolangBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

JSON (JavaScript Object Notation) est un format d'échange de données largement utilisé dans le développement web moderne et l'architecture des microservices. En Golang, le package intégré encoding/json offre un moyen simple et efficace de travailler avec les données JSON. L'une des fonctionnalités puissantes de ce package est l'utilisation des struct tags (étiquettes de structure), qui vous permettent de personnaliser la sérialisation et la désérialisation de vos structures de données. Ce tutoriel vous guidera dans la maîtrise de l'art d'utiliser les struct tags JSON en Golang, en couvrant les techniques avancées pour personnaliser la sérialisation JSON et tirer parti des struct tags pour la transformation et la configuration des données.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/DataTypesandStructuresGroup(["Data Types and Structures"]) go(("Golang")) -.-> go/AdvancedTopicsGroup(["Advanced Topics"]) go/DataTypesandStructuresGroup -.-> go/structs("Structs") go/AdvancedTopicsGroup -.-> go/json("JSON") subgraph Lab Skills go/structs -.-> lab-431222{{"Comment utiliser correctement les struct tags JSON"}} go/json -.-> lab-431222{{"Comment utiliser correctement les struct tags JSON"}} end

Maîtrise des struct tags JSON en Golang

JSON (JavaScript Object Notation) est un format d'échange de données léger largement utilisé dans le développement web moderne et l'architecture des microservices. En Golang, le package intégré encoding/json offre un moyen simple et efficace de travailler avec les données JSON. L'une des fonctionnalités puissantes de ce package est l'utilisation des struct tags (étiquettes de structure), qui vous permettent de personnaliser la sérialisation et la désérialisation de vos structures de données.

Comprendre les struct tags JSON

Les struct tags en Golang sont un moyen d'associer des métadonnées aux champs d'une structure. Le package encoding/json utilise ces étiquettes pour contrôler la manière dont les champs sont sérialisés et désérialisés lors de la manipulation de données JSON. La syntaxe de base d'une struct tag JSON est la suivante :

type MyStruct struct {
    FieldName string `json:"field_name"`
}

Dans cet exemple, la struct tag json:"field_name" indique au package encoding/json d'utiliser le nom "field_name" lors de la sérialisation ou de la désérialisation du champ FieldName.

Personnaliser la sérialisation et la désérialisation JSON

Les struct tags en Golang offrent un large éventail d'options pour personnaliser le processus de sérialisation et de désérialisation JSON. Voici quelques-unes des utilisations les plus courantes :

  1. Renommer des champs : Comme montré dans l'exemple précédent, vous pouvez utiliser la struct tag json:"field_name" pour renommer le nom du champ JSON.
  2. Ommettre des champs : Vous pouvez utiliser la struct tag json:"-" pour exclure un champ de la sortie JSON.
  3. Gérer les valeurs null : La struct tag json:",omitempty" omettra le champ de la sortie JSON si la valeur est la valeur zéro pour ce type.
  4. Gérer les structures imbriquées : Vous pouvez utiliser la struct tag json:"fieldName,inline" pour intégrer les champs d'une structure imbriquée.
  5. Gérer les types tableau et slice : La struct tag json:",string" peut être utilisée pour sérialiser un tableau ou une slice sous forme de chaîne de caractères séparée par des virgules.

Exemples pratiques

Explorons quelques exemples pratiques d'utilisation des struct tags JSON en Golang :

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name     string `json:"name"`
    Age      int    `json:"age"`
    Password string `json:"-"`
    Address  struct {
        Street  string `json:"street"`
        City    string `json:"city"`
        Country string `json:"country,omitempty"`
    } `json:"address"`
    Hobbies []string `json:",string"`
}

func main() {
    // Create a Person struct
    p := Person{
        Name:     "John Doe",
        Age:      30,
        Password: "secret",
        Address: struct {
            Street  string
            City    string
            Country string
        }{
            Street:  "123 Main St",
            City:    "Anytown",
            Country: "USA",
        },
        Hobbies: []string{"reading", "hiking", "photography"},
    }

    // Marshal the Person struct to JSON
    jsonData, _ := json.Marshal(p)
    fmt.Println(string(jsonData))
    // Output: {"name":"John Doe","age":30,"address":{"street":"123 Main St","city":"Anytown","country":"USA"},"Hobbies":"reading,hiking,photography"}

    // Unmarshal the JSON data to a Person struct
    var p2 Person
    json.Unmarshal(jsonData, &p2)
    fmt.Println(p2)
    // Output: {John Doe 30  {123 Main St Anytown USA} [reading hiking photography]}
}

Dans cet exemple, nous démontrons l'utilisation de diverses struct tags JSON :

  • Les champs Name, Age et Address sont sérialisés et désérialisés comme prévu.
  • Le champ Password est omis de la sortie JSON.
  • Le champ Country dans la structure Address n'est inclus dans la sortie JSON que s'il a une valeur non nulle.
  • La slice Hobbies est sérialisée sous forme de chaîne de caractères séparée par des virgules et désérialisée en une slice de chaînes de caractères.

En comprenant et en exploitant le potentiel des struct tags JSON en Golang, vous pouvez personnaliser efficacement la sérialisation et la désérialisation de vos structures de données, ce qui facilite la manipulation des données JSON dans vos applications.

Techniques avancées pour personnaliser la sérialisation JSON

Bien que les struct tags JSON de base couverts dans la section précédente soient très utiles, le package encoding/json de Golang propose également des techniques plus avancées pour personnaliser la sérialisation et la désérialisation de vos structures de données. Ces techniques vous permettent de gérer des scénarios complexes et d'obtenir un contrôle plus fin sur la représentation JSON de vos données.

Gérer omitempty et les noms de champs personnalisés

L'un des cas d'utilisation avancé le plus courant des struct tags JSON est de gérer la directive omitempty et de personnaliser les noms de champs. La directive omitempty indique au package encoding/json d'omettre un champ de la sortie JSON si la valeur du champ est la valeur zéro de son type. Cela peut être particulièrement utile lorsqu'il s'agit de champs nullable ou optionnels.

type Person struct {
    Name     string  `json:"name"`
    Age      int     `json:"age,omitempty"`
    Email    *string `json:"email,omitempty"`
    Password string  `json:"-"`
}

Dans cet exemple, les champs Age et Email seront omis de la sortie JSON s'ils ont leurs valeurs zéro (respectivement 0 et nil). Le champ Password est complètement exclu de la sortie JSON.

Vous pouvez également utiliser des noms de champs personnalisés pour mieux correspondre aux conventions de nommage de vos données JSON. Par exemple, vous pourriez vouloir utiliser des noms de champs en snake_case dans votre JSON, même si votre struct Go utilise le camelCase :

type Person struct {
    FullName string `json:"full_name"`
    DateOfBirth time.Time `json:"date_of_birth"`
}

Gérer les structs et les interfaces imbriquées

Le support de Golang pour les structs et les interfaces imbriquées peut également être exploité lors de la manipulation de données JSON. Vous pouvez utiliser la directive de struct tag inline pour intégrer directement les champs d'une struct imbriquée dans la représentation JSON de la struct parente.

type Address struct {
    Street  string `json:"street"`
    City    string `json:"city"`
    Country string `json:"country,omitempty"`
}

type Person struct {
    Name    string  `json:"name"`
    Address Address `json:"address,inline"`
}

Dans cet exemple, les champs de la struct Address sont intégrés dans la représentation JSON de la struct Person, ce qui donne une sortie JSON plus compacte et plus lisible.

De plus, vous pouvez utiliser des interfaces pour créer des structures JSON plus dynamiques et flexibles. En définissant les champs de votre struct comme des interfaces, vous pouvez sérialiser et désérialiser une plus grande variété de types de données, ce qui permet une gestion JSON plus polyvalente.

Encoders et décodeurs JSON personnalisés

Dans certains cas, la fonctionnalité intégrée du package encoding/json peut ne pas être suffisante pour gérer vos besoins spécifiques de sérialisation et de désérialisation JSON. Dans ces situations, vous pouvez créer des encodeurs et des décodeurs JSON personnalisés pour étendre les capacités du package.

Pour créer un encodeur ou un décodeur personnalisé, vous devez implémenter respectivement les interfaces json.Marshaler ou json.Unmarshaler. Cela vous permet de définir votre propre logique pour sérialiser et désérialiser vos structures de données.

type Person struct {
    Name string
    Age  int
}

func (p *Person) MarshalJSON() ([]byte, error) {
    return []byte(fmt.Sprintf(`{"name":"%s","age":%d}`, p.Name, p.Age)), nil
}

func (p *Person) UnmarshalJSON(data []byte) error {
    var v map[string]interface{}
    if err := json.Unmarshal(data, &v); err != nil {
        return err
    }
    p.Name, _ = v["name"].(string)
    p.Age, _ = v["age"].(int)
    return nil
}

En implémentant ces interfaces, vous pouvez complètement personnaliser le processus de sérialisation et de désérialisation JSON de vos structures de données, ce qui vous permet de gérer même les exigences JSON les plus complexes.

Exploitation des struct tags pour la transformation et la configuration des données

Au-delà de la fonctionnalité principale de sérialisation et de désérialisation JSON, les struct tags de Golang peuvent également être exploités pour des cas d'utilisation plus avancés, tels que la transformation des données et la gestion de la configuration. En étendant les capacités du package encoding/json, vous pouvez créer des pipelines de traitement de données puissants et flexibles qui s'intègrent parfaitement à l'architecture de votre application.

Transformation des données avec les struct tags

Les struct tags peuvent être utilisés pour transformer des données entre différentes représentations ou formats. Cela est particulièrement utile lorsqu'il s'agit de travailler avec des systèmes hérités, des API tierces ou des sources de données qui utilisent des conventions de nommage ou des structures de données différentes de celles du modèle de données interne de votre application.

type LegacyData struct {
    FirstName string `json:"first_name"`
    LastName  string `json:"last_name"`
    Age       int    `json:"age"`
}

type ModernData struct {
    FullName string `json:"full_name"`
    YearsOld int    `json:"years_old"`
}

func TransformData(legacy *LegacyData) ModernData {
    return ModernData{
        FullName: fmt.Sprintf("%s %s", legacy.FirstName, legacy.LastName),
        YearsOld: legacy.Age,
    }
}

Dans cet exemple, la fonction TransformData prend une struct LegacyData et la transforme en une struct ModernData, en mappant les champs en conséquence. En utilisant les struct tags, vous pouvez vous assurer que le processus de sérialisation et de désérialisation JSON est transparent, même lorsque la représentation interne des données diffère du format de données externe.

Gestion de la configuration avec les struct tags

Les struct tags peuvent également être utilisés pour gérer la configuration de l'application, ce qui facilite le chargement et la validation des données de configuration à partir de diverses sources, telles que les variables d'environnement, les fichiers de configuration ou les arguments de ligne de commande.

type AppConfig struct {
    ServerPort int    `env:"SERVER_PORT" default:"8080"`
    DatabaseURL string `env:"DATABASE_URL" required:"true"`
    LogLevel   string `env:"LOG_LEVEL" default:"info"`
}

func LoadConfig() (*AppConfig, error) {
    var config AppConfig
    if err := envconfig.Process("", &config); err != nil {
        return nil, err
    }
    return &config, nil
}

Dans cet exemple, nous utilisons le package envconfig (qui peut être installé via go get github.com/kelseyhightower/envconfig) pour charger la configuration de l'application à partir des variables d'environnement. Les struct tags définissent les noms des variables d'environnement, les valeurs par défaut et si un champ est obligatoire. Cette approche vous permet de gérer facilement la configuration de votre application, la rendant plus maintenable et adaptable à différents environnements de déploiement.

En exploitant les struct tags pour la transformation des données et la gestion de la configuration, vous pouvez créer des applications Golang plus robustes et flexibles qui s'intègrent parfaitement à diverses sources de données et environnements de déploiement.

Résumé

Dans ce tutoriel, vous avez appris à exploiter le potentiel des struct tags JSON en Golang pour personnaliser la sérialisation et la désérialisation de vos structures de données. Vous avez exploré divers cas d'utilisation, tels que le renommage de champs, l'omission de champs, la gestion des valeurs null, le travail avec des structs imbriquées et la sérialisation de tableaux et de slices. En maîtrisant les techniques présentées dans ce guide, vous pouvez désormais travailler de manière efficace et flexible avec les données JSON dans vos applications Golang, adaptant le processus de sérialisation à vos besoins spécifiques.