encoding/json mit Structs
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 76 von 107.
Das encoding/json-Paket ermöglicht es Ihnen, Go-Structs in JSON und zurück zu konvertieren. Dies ist essenziell für APIs, Konfigurationsdateien und Datenspeicherung. Struct-Tags steuern, wie Felder auf JSON-Schlüssel abgebildet werden.
Um ein Struct in JSON zu konvertieren, verwenden Sie 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}
}Die Struct-Tags wie `json:"name"` legen die JSON-Schlüsselnamen fest. Ohne Tags verwendet Go den Feldnamen direkt. Nur exportierte Felder (großgeschrieben) werden in die JSON-Ausgabe aufgenommen.
Um JSON wieder in ein Struct umzuwandeln, verwenden Sie json.Unmarshal:
jsonStr := `{"name":"Bob","email":"bob@example.com","age":25}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
fmt.Println(user.Name) // BobZu den gängigen Tag-Optionen gehören omitempty, um Nullwerte zu überspringen, und -, um ein Feld vollständig zu ignorieren:
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price,omitempty"`
Internal string `json:"-"`
}Mit omitempty wird Price, wenn es null ist, nicht im JSON erscheinen. Das Feld Internal wird unabhängig von seinem Wert niemals einbezogen.
Aufgabe
EinfachLassen wir uns ein Filmkatalog-System bauen, das zwischen Go-Structs und JSON konvertiert! Du wirst üben, Structs in JSON zu marshalen und JSON zurück in Structs zu unmarshalen, wobei du Struct-Tags verwendest, um die JSON-Feldnamen zu steuern.
Du wirst deinen Code in zwei Dateien organisieren:
movie.go: Definiere dein Film-Datenmodell mit den richtigen JSON-Tags.Erstelle ein
MovieStruct mit den folgenden Feldern und JSON-Mappings:Title(string) wird auf"title"gemapptDirector(string) wird auf"director"gemapptYear(int) wird auf"year"gemapptRating(float64) wird auf"rating"mitomitemptygemappt, damit unbewertete Filme kein Rating-Feld anzeigenInternalID(string) sollte mit"-"vollständig aus dem JSON ausgeschlossen werden
Erstelle eine Funktion
ToJSON(m Movie) string, die ein Movie in einen JSON-String konvertiert. Erstelle außerdemFromJSON(jsonStr string) Movie, die einen JSON-String zurück in ein Movie-Struct parst.main.go: Demonstriere die JSON-Konvertierung in beide Richtungen.Lies einen Operationstyp ein (
"encode"oder"decode").Für
"encode": Lies die Filmdetails (Titel, Regisseur, Jahr, Bewertung) in separaten Zeilen ein. Erstelle ein Movie mit einer InternalID von"internal-123", konvertiere es in JSON und gib das Ergebnis aus.Für
"decode": Lies einen JSON-String ein, konvertiere ihn in ein Movie-Struct und gib die Filmdetails in diesem Format aus:Title: [title] Director: [director] Year: [year] Rating: [rating]Zeige die Bewertung mit einer Dezimalstelle an. Wenn die Bewertung 0 ist (nicht im JSON vorhanden), gib stattdessen
"Rating: N/A"aus.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Operationstyp (
"encode"oder"decode") - Für encode: Titel, Regisseur, Jahr, Bewertung (vier Zeilen)
- Für decode: ein JSON-String (eine Zeile)
Zum Beispiel, gegeben:
encode
Inception
Christopher Nolan
2010
8.8Deine Ausgabe sollte sein:
{"title":"Inception","director":"Christopher Nolan","year":2010,"rating":8.8}Beachte, dass InternalID aufgrund des "-" Tags nicht in der Ausgabe erscheint.
Und gegeben:
encode
The Matrix
Wachowskis
1999
0Deine Ausgabe sollte sein:
{"title":"The Matrix","director":"Wachowskis","year":1999}Beachte, dass "rating" weggelassen wird, weil es Null ist und omitempty hat.
Und gegeben:
decode
{"title":"Interstellar","director":"Christopher Nolan","year":2014,"rating":8.6}Deine Ausgabe sollte sein:
Title: Interstellar
Director: Christopher Nolan
Year: 2014
Rating: 8.6Und gegeben:
decode
{"title":"Tenet","director":"Christopher Nolan","year":2020}Deine Ausgabe sollte sein:
Title: Tenet
Director: Christopher Nolan
Year: 2020
Rating: N/ASpickzettel
Das Paket encoding/json konvertiert Go-Structs in JSON und umgekehrt unter Verwendung von json.Marshal und json.Unmarshal.
Um ein Struct in JSON zu konvertieren:
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}Um JSON wieder in ein Struct zu konvertieren:
jsonStr := `{"name":"Bob","email":"bob@example.com","age":25}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
fmt.Println(user.Name) // BobStruct-Tags steuern das JSON-Feld-Mapping:
`json:"name"`- bildet das Feld auf den JSON-Schlüssel "name" ab`json:"price,omitempty"`- lässt das Feld weg, wenn es der Nullwert ist`json:"-"`- schließt das Feld vollständig aus JSON aus
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price,omitempty"`
Internal string `json:"-"`
}Nur exportierte Felder (großgeschrieben) werden in die JSON-Ausgabe einbezogen.
Probier es selbst
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Operationstyp lesen
operation, _ := reader.ReadString('\n')
operation = strings.TrimSpace(operation)
if operation == "encode" {
// Filmdetails lesen
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: Erstelle eine Movie-Struktur mit den gelesenen Werten
// Setze InternalID auf "internal-123"
// Konvertiere mit ToJSON zu JSON und gib das Ergebnis aus
} else if operation == "decode" {
// JSON-String lesen
jsonStr, _ := reader.ReadString('\n')
jsonStr = strings.TrimSpace(jsonStr)
// TODO: Konvertiere JSON mit FromJSON zu Movie
// Gib die Filmdetails im erforderlichen Format aus
// Verwende fmt.Sprintf("%.1f", rating) für die Formatierung der Bewertung
// Wenn rating 0 ist, gib stattdessen "Rating: N/A" aus
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der Go OOP
Externe DateienGo Workspace & ModulePackages & ImportsExportierte vs. nicht-exportierte NamenEinführung in OOP in GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktor-FunktionenZusammenfassung – Einfacher Taschenrechner4Interfaces
Einführung in InterfacesImplizite ImplementierungInterface als VertragLeeres Interface (any)Type AssertionType SwitchInterface-KompositionStringer & Error InterfacesRückblick - Formen-Rechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf Paket-EbeneGetter- & Setter-MethodenInformation Hiding in GoZusammenfassung - Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterType ConstraintsGenerische StructsWorkaround für generische MethodenZusammenfassung – Generische Collection2Vertiefung: Typen & Structs
Basis- & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct TagsAnonyme StructsVerschachtelte StructsZero Values & StandardwerteZusammenfassung - Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen des Struct EmbeddingMethod PromotionEinbetten mehrerer StructsEmbedding vs. AggregationShadowing eingebetteter MethodenZusammenfassung – Mitarbeiter-Hierarchie8Fehlerbehandlung & OOP
Das error-InterfaceEigene FehlertypenError Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverZusammenfassung – Datei-Parser11Standardbibliothek & OOP
io.Reader & io.Writersort.Interfacefmt.Stringer Interfaceencoding/json mit Structshttp.Handler InterfaceZusammenfassung - REST-API-Modelle3Zeiger & Speicher
Zeiger-Grundlagen in GoZeiger auf StructsWertübergabe vs. ReferenzübergabeDie new() FunktionGarbage Collection in GoWiederholung – Linked List Builder6Polymorphismus in Go
Polymorphismus über InterfacesDuck Typing in GoInterface-ErfüllungsregelnPolymorphe CollectionsDependency InjectionZusammenfassung – Payment Processor9Nebenläufigkeit & OOP
Goroutines GrundlagenChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignZusammenfassung - Worker Pool