encoding/json avec les Structs
Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy — leçon 76 sur 107.
Le paquet encoding/json vous permet de convertir des structures Go en JSON et inversement. C'est essentiel pour les API, les fichiers de configuration et le stockage de données. Les balises de structure (struct tags) contrôlent la manière dont les champs sont mis en correspondance avec les clés JSON.
Pour convertir une struct en JSON, utilisez json.Marshal :
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
}
func main() {
user := User{Name: "Alice", Email: "alice@example.com", Age: 30}
data, _ := json.Marshal(user)
fmt.Println(string(data))
// {"name":"Alice","email":"alice@example.com","age":30}
}Les tags de struct comme `json:"name"` spécifient les noms des clés JSON. Sans tags, Go utilise directement le nom du champ. Seuls les champs exportés (commençant par une majuscule) sont inclus dans la sortie JSON.
Pour reconvertir du JSON en une structure, utilisez json.Unmarshal :
jsonStr := `{"name":"Bob","email":"bob@example.com","age":25}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
fmt.Println(user.Name) // BobLes options de balises courantes incluent omitempty pour ignorer les valeurs par défaut et - pour ignorer complètement un champ :
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price,omitempty"`
Internal string `json:"-"`
}Avec omitempty, si Price vaut zéro, il n'apparaîtra pas dans le JSON. Le champ Internal n'est jamais inclus, quelle que soit sa valeur.
Défi
FacileConstruisons un système de catalogue de films qui convertit des structs Go en JSON et vice-versa ! Vous allez vous entraîner à transformer des structs en JSON (marshaling) et à transformer du JSON en structs (unmarshaling), en utilisant des tags de struct pour contrôler les noms des champs JSON.
Vous organiserez votre code sur deux fichiers :
movie.go: Définissez votre modèle de données de film avec les tags JSON appropriés.Créez une struct
Movieavec les champs et les mappages JSON suivants :Title(string) correspond à"title"Director(string) correspond à"director"Year(int) correspond à"year"Rating(float64) correspond à"rating"avecomitemptypour que les films non notés n'affichent pas de champ de notationInternalID(string) doit être totalement exclu du JSON en utilisant"-"
Créez une fonction
ToJSON(m Movie) stringqui convertit un Movie en une chaîne JSON. Créez égalementFromJSON(jsonStr string) Moviequi analyse une chaîne JSON pour la transformer en une struct Movie.main.go: Démontrez la conversion JSON dans les deux sens.Lisez un type d'opération (
encodeoudecode).Pour
encode: Lisez les détails du film (titre, réalisateur, année, note) sur des lignes séparées. Créez un Movie avec un InternalID de"internal-123", convertissez-le en JSON et affichez le résultat.Pour
decode: Lisez une chaîne JSON, convertissez-la en une struct Movie et affichez les détails du film dans ce format :Title: [title] Director: [director] Year: [year] Rating: [rating]Affichez la note avec une décimale. Si la note est 0 (absente du JSON), affichez
Rating: N/Aà la place.
Les entrées suivantes seront fournies :
- Ligne 1 : Type d'opération (
encodeoudecode) - Pour encode : titre, réalisateur, année, note (quatre lignes)
- Pour decode : une chaîne JSON (une ligne)
Par exemple, avec :
encode
Inception
Christopher Nolan
2010
8.8Votre sortie devrait être :
{"title":"Inception","director":"Christopher Nolan","year":2010,"rating":8.8}Notez que InternalID n'apparaît pas dans la sortie à cause du tag "-".
Et avec :
encode
The Matrix
Wachowskis
1999
0Votre sortie devrait être :
{"title":"The Matrix","director":"Wachowskis","year":1999}Notez que rating est omis car il est égal à zéro et possède l'option omitempty.
Et avec :
decode
{"title":"Interstellar","director":"Christopher Nolan","year":2014,"rating":8.6}Votre sortie devrait être :
Title: Interstellar
Director: Christopher Nolan
Year: 2014
Rating: 8.6Et avec :
decode
{"title":"Tenet","director":"Christopher Nolan","year":2020}Votre sortie devrait être :
Title: Tenet
Director: Christopher Nolan
Year: 2020
Rating: N/AAide-mémoire
Le paquet encoding/json convertit les structures Go en JSON et vice versa en utilisant json.Marshal et json.Unmarshal.
Pour convertir une structure en JSON :
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
}
user := User{Name: "Alice", Email: "alice@example.com", Age: 30}
data, _ := json.Marshal(user)
fmt.Println(string(data))
// {"name":"Alice","email":"alice@example.com","age":30}Pour reconvertir du JSON en structure :
jsonStr := `{"name":"Bob","email":"bob@example.com","age":25}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
fmt.Println(user.Name) // BobLes balises de structure (struct tags) contrôlent le mappage des champs JSON :
`json:"name"`- mappe le champ à la clé JSON "name"`json:"price,omitempty"`- omet le champ si la valeur est nulle (zero value)`json:"-"`- exclut complètement le champ du JSON
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price,omitempty"`
Internal string `json:"-"`
}Seuls les champs exportés (commençant par une majuscule) sont inclus dans la sortie JSON.
Essayez vous-même
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Lire le type d'opération
operation, _ := reader.ReadString('\n')
operation = strings.TrimSpace(operation)
if operation == "encode" {
// Lire les détails du film
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
director, _ := reader.ReadString('\n')
director = strings.TrimSpace(director)
yearStr, _ := reader.ReadString('\n')
yearStr = strings.TrimSpace(yearStr)
year, _ := strconv.Atoi(yearStr)
ratingStr, _ := reader.ReadString('\n')
ratingStr = strings.TrimSpace(ratingStr)
rating, _ := strconv.ParseFloat(ratingStr, 64)
// TODO: Créer une struct Movie avec les valeurs lues
// Définir InternalID à "internal-123"
// Convertir en JSON en utilisant ToJSON et afficher le résultat
} else if operation == "decode" {
// Lire la chaîne JSON
jsonStr, _ := reader.ReadString('\n')
jsonStr = strings.TrimSpace(jsonStr)
// TODO: Convertir le JSON en Movie en utilisant FromJSON
// Afficher les détails du film au format requis
// Utiliser fmt.Sprintf("%.1f", rating) pour le formatage de rating
// Si rating est 0, afficher "Rating: N/A" à la place
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO en Go
Fichiers externesEspace de travail et Modules GoPackages et ImportsNoms exportés vs non exportésIntroduction à la POO en GoLes Structs comme ClassesDéfinir des méthodes sur les StructsReceveurs par pointeur vs par valeurInitialisation de StructsFonctions constructeursRécapitulatif - Calculatrice simple4Interfaces
Introduction aux interfacesImplémentation impliciteL'interface comme contratInterface vide (any)Assertion de typeType SwitchComposition d'interfacesInterfaces Stringer & ErrorRécapitulatif - Calculateur de formes7Encapsulation
Champs exportés vs non exportésEncapsulation au niveau du packageMéthodes Getter & SetterMasquage d'informations en GoRécapitulatif - Dossiers étudiants10Génériques (Go 1.18+)
Introduction aux génériquesParamètres de typeContraintes de typeStructures génériquesContournement pour les méthodes génériquesRécapitulatif - Collections génériques13Patrons de conception, Partie 1
Introduction aux Design PatternsPatron SingletonPatron FactoryPatron Abstract FactoryPatron ObserverPatron Strategy2Exploration approfondie des Types et Structs
Types de base et compositesDéfinitions de types personnalisésTags de StructStructs anonymesStructs imbriquéesValeurs par défaut et Zero ValuesRécapitulatif - Carnet de contacts5Composition plutôt qu'héritage
Pourquoi Go n'a pas d'héritageLes bases de l'imbrication de structsPromotion de méthodesImbriquer plusieurs structsImbrication vs AgrégationMasquage de méthodes imbriquéesRécapitulatif - Hiérarchie des employés8Gestion des erreurs & POO
L'interface errorTypes d'erreurs personnalisésError Wrapping (fmt.Errorf)Erreurs sentinelleserrors.Is() et errors.As()Panic, Defer et RecoverRécapitulatif - File Parser11Bibliothèque standard et POO
io.Reader & io.WriterL'interface sort.InterfaceL'interface fmt.Stringerencoding/json avec les StructsL'interface http.HandlerRécapitulatif - Modèles d'API REST14Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositeMiddleware en tant que Décorateur3Pointeurs et Mémoire
Bases des pointeurs en GoPointeurs vers des structsPassage par valeur vs référenceLa fonction new()Garbage Collection en GoRécapitulatif - Constructeur de liste chaînée6Le polymorphisme en Go
Le polymorphisme via les interfacesLe Duck Typing en GoRègles de satisfaction des interfacesCollections polymorphesInjection de dépendancesRécapitulatif - Processeur de paiement9Concurrence et POO
Bases des GoroutinesChannels et CommunicationChannels avec buffer vs sans bufferL'instruction Selectsync.Mutex et sync.RWMutexsync.WaitGroupConception de structures Thread-SafeRécapitulatif - Worker Pool