Menu
Coddy logo textTech

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

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

challenge icon

Aufgabe

Einfach

Lassen 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 Movie Struct mit den folgenden Feldern und JSON-Mappings:

    • Title (string) wird auf "title" gemappt
    • Director (string) wird auf "director" gemappt
    • Year (int) wird auf "year" gemappt
    • Rating (float64) wird auf "rating" mit omitempty gemappt, damit unbewertete Filme kein Rating-Feld anzeigen
    • InternalID (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ßerdem FromJSON(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.8

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

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

Und gegeben:

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

Deine Ausgabe sollte sein:

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

Spickzettel

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

Struct-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

	}
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung