Menu
Coddy logo textTech

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)  // Bob

Les 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.

challenge icon

Défi

Facile

Construisons 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 Movie avec les champs et les mappages JSON suivants :

    • Title (string) correspond à "title"
    • Director (string) correspond à "director"
    • Year (int) correspond à "year"
    • Rating (float64) correspond à "rating" avec omitempty pour que les films non notés n'affichent pas de champ de notation
    • InternalID (string) doit être totalement exclu du JSON en utilisant "-"

    Créez une fonction ToJSON(m Movie) string qui convertit un Movie en une chaîne JSON. Créez également FromJSON(jsonStr string) Movie qui 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 (encode ou decode).

    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 (encode ou decode)
  • 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.8

Votre 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
0

Votre 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.6

Et avec :

decode
{"title":"Tenet","director":"Christopher Nolan","year":2020}

Votre sortie devrait être :

Title: Tenet
Director: Christopher Nolan
Year: 2020
Rating: N/A

Aide-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)  // Bob

Les 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

	}
}
quiz iconTestez-vous

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