encoding/json con le struct
Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 76 di 107.
Il pacchetto encoding/json ti permette di convertire le struct Go in JSON e viceversa. Questo è essenziale per le API, i file di configurazione e l'archiviazione dei dati. I tag delle struct controllano come i campi vengono associati alle chiavi JSON.
Per convertire una struct in JSON, usa 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}
}I tag struct come `json:"name"` specificano i nomi delle chiavi JSON. Senza tag, Go usa direttamente il nome del campo. Nell’output JSON sono inclusi solo i campi esportati (con iniziale maiuscola).
Per convertire JSON di nuovo in una struct, usa json.Unmarshal:
jsonStr := `{"name":"Bob","email":"bob@example.com","age":25}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
fmt.Println(user.Name) // BobLe opzioni comuni dei tag includono omitempty per ignorare i valori zero e - per ignorare completamente un campo:
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price,omitempty"`
Internal string `json:"-"`
}Con omitempty, se Price è zero, non comparirà nel JSON. Il campo Internal non viene mai incluso, indipendentemente dal suo valore.
Sfida
FacileCreiamo un sistema di catalogo cinematografico che converte tra struct Go e JSON! Ti eserciterai a eseguire il marshaling delle struct in JSON e l'unmarshaling del JSON nelle struct, usando i tag delle struct per controllare i nomi dei campi JSON.
Organizzerai il codice in due file:
movie.go: Definisci il modello dei dati dei film con i tag JSON appropriati.Crea una struct
Moviecon i seguenti campi e mappature JSON:Title(string) corrisponde a"title"Director(string) corrisponde a"director"Year(int) corrisponde a"year"Rating(float64) corrisponde a"rating"conomitempty, così i film senza valutazione non mostrano il campo della valutazioneInternalID(string) deve essere escluso completamente dal JSON usando"-"
Crea una funzione
ToJSON(m Movie) stringche converte una Movie in una stringa JSON. Crea ancheFromJSON(jsonStr string) Movie, che analizza una stringa JSON e la riconverte in una struct Movie.main.go: Mostra la conversione JSON in entrambe le direzioni.Leggi un tipo di operazione (
encodeodecode).Per
encode: Leggi i dettagli del film (titolo, regista, anno, valutazione) su righe separate. Crea una Movie con un InternalID pari a"internal-123", convertila in JSON e stampa il risultato.Per
decode: Leggi una stringa JSON, convertila in una struct Movie e stampa i dettagli del film in questo formato:Title: [title] Director: [director] Year: [year] Rating: [rating]Mostra la valutazione con una cifra decimale. Se la valutazione è 0 (non presente nel JSON), stampa invece
Rating: N/A.
Verranno forniti i seguenti input:
- Riga 1: tipo di operazione (
encodeodecode) - Per encode: titolo, regista, anno, valutazione (quattro righe)
- Per decode: una stringa JSON (una riga)
Ad esempio, dato:
encode
Inception
Christopher Nolan
2010
8.8L'output dovrebbe essere:
{"title":"Inception","director":"Christopher Nolan","year":2010,"rating":8.8}Nota che InternalID non compare nell'output a causa del tag "-".
E dato:
encode
The Matrix
Wachowskis
1999
0L'output dovrebbe essere:
{"title":"The Matrix","director":"Wachowskis","year":1999}Nota che rating viene omesso perché è zero e ha omitempty.
E dato:
decode
{"title":"Interstellar","director":"Christopher Nolan","year":2014,"rating":8.6}L'output dovrebbe essere:
Title: Interstellar
Director: Christopher Nolan
Year: 2014
Rating: 8.6E dato:
decode
{"title":"Tenet","director":"Christopher Nolan","year":2020}L'output dovrebbe essere:
Title: Tenet
Director: Christopher Nolan
Year: 2020
Rating: N/AProvalo tu
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Leggi il tipo di operazione
operation, _ := reader.ReadString('\n')
operation = strings.TrimSpace(operation)
if operation == "encode" {
// Leggi i dettagli del 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: Crea una struct Movie con i valori letti
// Imposta InternalID su "internal-123"
// Converti in JSON usando ToJSON e stampa il risultato
} else if operation == "decode" {
// Leggi la stringa JSON
jsonStr, _ := reader.ReadString('\n')
jsonStr = strings.TrimSpace(jsonStr)
// TODO: Converti JSON in Movie usando FromJSON
// Stampa i dettagli del film nel formato richiesto
// Usa fmt.Sprintf("%.1f", rating) per formattare rating
// Se rating è 0, stampa invece "Rating: N/A"
}
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti di OOP in Go
File esterniWorkspace e moduli GoPacchetti e importazioniNomi esportati e non esportatiIntroduzione all’OOP in GoGli struct come classiDefinire metodi sugli structReceiver con puntatore vs receiver con valoreInizializzazione degli structFunzioni costruttriciRiepilogo - Calcolatrice semplice4Interfacce
Introduzione alle interfacceImplementazione implicitaL’interfaccia come contrattoInterfaccia vuota (any)Asserzione di tipoSwitch sul tipoComposizione di interfacceInterfacce Stringer ed ErrorRipasso - Calcolatore di forme7Incapsulamento
Campi esportati e non esportatiIncapsulamento a livello di packageMetodi Getter e SetterNascondimento delle informazioni in GoRiepilogo - Registri degli studenti10Tipi generici (Go 1.18+)
Introduzione ai tipi genericiParametri di tipoVincoli di tipoStruct genericheSoluzione alternativa per i metodi genericiRiepilogo - Collezione generica13Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneModello SingletonModello FactoryModello Abstract FactoryModello ObserverModello Strategy2Approfondimento su tipi e struct
Tipi di base e compostiDefinizioni di tipi personalizzatiTag delle structStruct anonimeStruct annidateValori zero e predefinitiRipasso - Rubrica5Composizione invece dell'ereditarietà
Perché Go non ha l'ereditarietàFondamenti dell'embedding delle structPromozione dei metodiEmbedding di più structEmbedding e aggregazione a confrontoMascheramento dei metodi embeddedRiepilogo: gerarchia dei dipendenti8Gestione degli errori e OOP
L'interfaccia errorTipi di errore personalizzatiWrapping degli errori (fmt.Errorf)Errori sentinellaerrors.Is() ed errors.As()Panic, Defer e RecoverRiepilogo - Parser di file11Libreria standard e OOP
io.Reader e io.Writersort.InterfaceInterfaccia fmt.Stringerencoding/json con le structInterfaccia http.HandlerRipasso - modelli REST API14Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeMiddleware come Decorator3Puntatori e memoria
Concetti base dei puntatori in GoPuntatori a structPassaggio per valore vs per riferimentoLa funzione new()Garbage collection in GoRiepilogo - Costruttore di liste concatenate6Polimorfismo in Go
Polimorfismo tramite interfacceDuck typing in GoRegole di soddisfacimento delle interfacceCollezioni polimorficheIniezione delle dipendenzeRiepilogo - Elaboratore di pagamenti9Concorrenza e OOP
Basi delle goroutineCanali e comunicazioneCanali bufferizzati vs non bufferizzatiIstruzione selectsync.Mutex e sync.RWMutexsync.WaitGroupProgettazione di struct thread-safeRiepilogo: worker poolEsercitati da solo: Compilatore Go online