encoding/json avec des structs
Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 76 sur 107.
Le package encoding/json vous permet de convertir des structs Go en JSON et inversement. C’est essentiel pour les API, les fichiers de configuration et le stockage des données. Les balises de struct contrôlent la manière dont les champs correspondent aux 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 balises de structure comme `json:"name"` spécifient les noms des clés JSON. Sans balises, 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 structures Go en JSON et inversement ! Tu vas t’entraîner à sérialiser des structures en JSON et à désérialiser du JSON en structures, en utilisant des balises de structure pour contrôler les noms des champs JSON.
Tu vas organiser ton code dans deux fichiers :
movie.go: définis ton modèle de données de film avec les balises JSON appropriées.Crée une structure
Movieavec les champs et les correspondances JSON suivants :Title(string) correspond à"title"Director(string) correspond à"director"Year(int) correspond à"year"Rating(float64) correspond à"rating"avecomitempty, afin que les films sans note n’affichent pas de champ de noteInternalID(string) doit être complètement exclu du JSON à l’aide de"-"
Crée une fonction
ToJSON(m Movie) stringqui convertit un Movie en chaîne JSON. Crée égalementFromJSON(jsonStr string) Moviequi analyse une chaîne JSON pour la reconvertir en structure Movie.main.go: montre la conversion JSON dans les deux sens.Lis un type d’opération (
encodeoudecode).Pour
encode: lis les détails du film (titre, réalisateur, année, note) sur des lignes séparées. Crée un Movie avec un InternalID égal à"internal-123", convertis-le en JSON et affiche le résultat.Pour
decode: lis une chaîne JSON, convertis-la en structure Movie et affiche les détails du film dans ce format :Title: [title] Director: [director] Year: [year] Rating: [rating]Affiche la note avec une décimale. Si la note est égale à 0 (absente du JSON), affiche
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.8Ta sortie doit être :
{"title":"Inception","director":"Christopher Nolan","year":2010,"rating":8.8}Remarque que InternalID n’apparaît pas dans la sortie à cause de la balise "-".
Et avec :
encode
The Matrix
Wachowskis
1999
0Ta sortie doit être :
{"title":"The Matrix","director":"Wachowskis","year":1999}Remarque que rating est omis, car sa valeur est zéro et qu’il possède omitempty.
Et avec :
decode
{"title":"Interstellar","director":"Christopher Nolan","year":2014,"rating":8.6}Ta sortie doit être :
Title: Interstellar
Director: Christopher Nolan
Year: 2014
Rating: 8.6Et avec :
decode
{"title":"Tenet","director":"Christopher Nolan","year":2020}Ta sortie doit être :
Title: Tenet
Director: Christopher Nolan
Year: 2020
Rating: N/AEssayez 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 et non exportésIntroduction à la POO en GoStructs comme classesDéfinir des méthodes sur des structsRécepteurs pointeurs ou par valeurInitialisation des structsFonctions constructeursRécapitulatif - Calculatrice simple4Interfaces
Introduction aux interfacesImplémentation impliciteL’interface comme contratInterface vide (any)Assertion de typeCommutation de typeComposition d’interfacesInterfaces Stringer et ErrorRécapitulatif - Calculateur de formes7Encapsulation
Champs exportés vs non exportésEncapsulation au niveau du packageMéthodes Getter et SetterDissimulation de l’information en GoRécapitulatif – Fiches d’étudiants10Génériques (Go 1.18+)
Introduction aux génériquesParamètres de typeContraintes de typeStructures génériquesSolution de contournement pour les méthodes génériquesRécapitulatif - Collection générique2Plongée approfondie dans les types et les structs
Types de base et compositesDéfinitions de types personnalisésTags de structStructs anonymesStructs imbriquésValeurs zéro et valeurs par défautRécapitulatif - Carnet de contacts5La composition plutôt que l’héritage
Pourquoi Go n’a pas d’héritageBases de l’inclusion de structsPromotion des méthodesInclure plusieurs structsInclusion ou agrégationMasquage des méthodes inclusesRécapitulatif : hiérarchie des employés8Gestion des erreurs et POO
L’interface errorTypes d’erreurs personnalisésEnrobage des erreurs (fmt.Errorf)Erreurs sentinelleserrors.Is() et errors.As()Panic, Defer et RecoverRécapitulatif - Analyseur de fichiers11Bibliothèque standard et POO
io.Reader et io.Writersort.InterfaceInterface fmt.Stringerencoding/json avec des structsInterface http.HandlerRécapitulatif - Modèles d’API REST14Modèles de conception – Partie 2
Modèle CommandeModèle AdaptateurModèle DécorateurModèle Méthode modèleModèle ÉtatModèle CompositeMiddleware comme décorateur3Pointeurs et mémoire
Notions de base des pointeurs en GoPointeurs vers des structuresPassage par valeur ou par référenceLa fonction new()Garbage collection en GoRécapitulatif - Constructeur de listes chaînées6Polymorphisme en Go
Polymorphisme via les interfacesDuck typing en GoRègles de satisfaction des interfacesCollections polymorphesInjection de dépendancesRécapitulatif – Processeur de paiements9Concurrence et POO
Bases des GoroutinesCanaux et communicationCanaux tamponnés ou non tamponnésInstruction selectsync.Mutex et sync.RWMutexsync.WaitGroupConception de structures thread-safeRécapitulatif - Pool de workersEntraînez-vous par vous-même : Compilateur Go en ligne