encoding/json ze strukturami
Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 76 z 107.
Pakiet encoding/json pozwala konwertować struktury Go na JSON i z powrotem. Jest to niezbędne w przypadku interfejsów API, plików konfiguracyjnych i przechowywania danych. Tagi struktur kontrolują sposób mapowania pól na klucze JSON.
Aby przekonwertować strukturę na JSON, użyj 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}
}Tagi struktury, takie jak `json:"name"`, określają nazwy kluczy JSON. Bez tagów Go używa bezpośrednio nazwy pola. W wyniku JSON uwzględniane są tylko eksportowane pola (zaczynające się wielką literą).
Aby przekonwertować JSON z powrotem na strukturę, użyj json.Unmarshal:
jsonStr := `{"name":"Bob","email":"bob@example.com","age":25}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
fmt.Println(user.Name) // BobTypowe opcje tagów obejmują omitempty, aby pomijać wartości zerowe, oraz -, aby całkowicie ignorować pole:
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price,omitempty"`
Internal string `json:"-"`
}Dzięki omitempty, jeśli Price ma wartość zero, nie pojawi się w JSON. Pole Internal nigdy nie jest uwzględniane, niezależnie od swojej wartości.
Wyzwanie
ŁatwyStwórzmy system katalogu filmów, który konwertuje między strukturami Go a JSON! Poćwiczysz serializowanie struktur do JSON i deserializowanie JSON z powrotem do struktur, używając tagów struktur do kontrolowania nazw pól JSON.
Rozmieścisz swój kod w dwóch plikach:
movie.go: Zdefiniuj model danych filmu z odpowiednimi tagami JSON.Utwórz strukturę
Moviez następującymi polami i mapowaniami JSON:Title(string) mapuje na"title"Director(string) mapuje na"director"Year(int) mapuje na"year"Rating(float64) mapuje na"rating"zomitempty, aby filmy bez oceny nie wyświetlały pola ocenyInternalID(string) powinno być całkowicie wykluczone z JSON przy użyciu"-"
Utwórz funkcję
ToJSON(m Movie) string, która konwertuje Movie na ciąg JSON. Utwórz teżFromJSON(jsonStr string) Movie, która analizuje ciąg JSON i konwertuje go z powrotem na strukturę Movie.main.go: Zademonstruj konwersję JSON w obu kierunkach.Odczytaj typ operacji (
encodelubdecode).Dla
encode: Odczytaj szczegóły filmu (tytuł, reżyser, rok, ocena) w osobnych wierszach. Utwórz Movie z InternalID o wartości"internal-123", przekonwertuj go na JSON i wyświetl wynik.Dla
decode: Odczytaj ciąg JSON, przekonwertuj go na strukturę Movie i wyświetl szczegóły filmu w następującym formacie:Title: [title] Director: [director] Year: [year] Rating: [rating]Wyświetl ocenę z jednym miejscem po przecinku. Jeśli ocena wynosi 0 (nie występuje w JSON), wyświetl
Rating: N/A.
Dane wejściowe będą następujące:
- Wiersz 1: Typ operacji (
encodelubdecode) - Dla encode: tytuł, reżyser, rok, ocena (cztery wiersze)
- Dla decode: ciąg JSON (jeden wiersz)
Na przykład, dla danych:
encode
Inception
Christopher Nolan
2010
8.8Wynik powinien być następujący:
{"title":"Inception","director":"Christopher Nolan","year":2010,"rating":8.8}Zauważ, że InternalID nie pojawia się w wyniku ze względu na tag "-".
A dla danych:
encode
The Matrix
Wachowskis
1999
0Wynik powinien być następujący:
{"title":"The Matrix","director":"Wachowskis","year":1999}Zauważ, że rating jest pomijane, ponieważ jego wartość wynosi zero i ma tag omitempty.
A dla danych:
decode
{"title":"Interstellar","director":"Christopher Nolan","year":2014,"rating":8.6}Wynik powinien być następujący:
Title: Interstellar
Director: Christopher Nolan
Year: 2014
Rating: 8.6A dla danych:
decode
{"title":"Tenet","director":"Christopher Nolan","year":2020}Wynik powinien być następujący:
Title: Tenet
Director: Christopher Nolan
Year: 2020
Rating: N/ASpróbuj swoich sił
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Odczytaj typ operacji
operation, _ := reader.ReadString('\n')
operation = strings.TrimSpace(operation)
if operation == "encode" {
// Odczytaj dane filmu
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: Utwórz strukturę Movie z odczytanymi wartościami
// Ustaw InternalID na "internal-123"
// Przekonwertuj na JSON za pomocą ToJSON i wypisz wynik
} else if operation == "decode" {
// Odczytaj ciąg znaków JSON
jsonStr, _ := reader.ReadString('\n')
jsonStr = strings.TrimSpace(jsonStr)
// TODO: Przekonwertuj JSON na Movie za pomocą FromJSON
// Wypisz dane filmu w wymaganym formacie
// Użyj fmt.Sprintf("%.1f", rating) do sformatowania rating
// Jeśli rating wynosi 0, wypisz zamiast tego "Rating: N/A"
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP w Go
Pliki zewnętrzneObszar roboczy i moduły GoPakiety i importyNazwy eksportowane i nieeksportowaneWprowadzenie do OOP w GoStruktury jako klasyDefiniowanie metod dla strukturOdbiorniki wskaźnikowe i wartościoweInicjalizacja strukturFunkcje konstruktoraPodsumowanie – prosty kalkulator4Interfejsy
Wprowadzenie do interfejsówImplementacja niejawnaInterfejs jako kontraktPusty interfejs (any)Asercja typuPrzełącznik typówKompozycja interfejsówInterfejsy Stringer i ErrorPowtórka — kalkulator figur7Hermetyzacja
Pola eksportowane i nieeksportowaneHermetyzacja na poziomie pakietuMetody pobierające i ustawiająceUkrywanie informacji w GoPowtórka – dane studentów10Typy generyczne (Go 1.18+)
Wprowadzenie do typów generycznychParametry typówOgraniczenia typówStruktury generyczneObejście ograniczeń metod generycznychPodsumowanie — generyczna kolekcja2Typy i struktury w praktyce
Typy proste i złożoneDefiniowanie własnych typówTagi pól strukturStruktury anonimoweStruktury zagnieżdżoneWartości zerowe i domyślnePodsumowanie – książka kontaktów5Kompozycja zamiast dziedziczenia
Dlaczego Go nie ma dziedziczeniaPodstawy osadzania strukturPromowanie metodOsadzanie wielu strukturOsadzanie a agregacjaPrzesłanianie osadzonych metodPodsumowanie — hierarchia pracowników8Obsługa błędów i programowanie obiektowe
Interfejs błęduWłasne typy błędówOpakowywanie błędów (fmt.Errorf)Błędy wartowniczeerrors.Is() i errors.As()Panic, Defer i RecoverPodsumowanie — parser plików11Biblioteka standardowa i OOP
io.Reader i io.Writersort.InterfaceInterfejs fmt.Stringerencoding/json ze strukturamiInterfejs http.HandlerPowtórzenie – modele REST API3Wskaźniki i pamięć
Podstawy wskaźników w GoWskaźniki do strukturPrzekazywanie przez wartość a przez referencjęFunkcja new()Odśmiecanie pamięci w GoPowtórka — kreator listy wiązanej6Polimorfizm w Go
Polimorfizm za pomocą interfejsówDuck typing w GoZasady spełniania interfejsówKolekcje polimorficzneWstrzykiwanie zależnościPowtórka — procesor płatności9Współbieżność i OOP
Podstawy goroutinesKanały i komunikacjaKanały buforowane i niebuforowaneInstrukcja selectsync.Mutex i sync.RWMutexsync.WaitGroupProjektowanie struktur bezpiecznych wątkowoPowtórka – pula workerów12Zaawansowane zagadnienia programowania obiektowego
Wzorzec opcji funkcyjnychWzorzec Builder w GoŁańcuchowe wywoływanie metodAliasy typów a definicje typówPodstawy refleksjiPrzegląd generowania koduPoćwicz samodzielnie: Kompilator Go online