Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym samouczku utworzysz aplikację, która wysyła żądania HTTP do usługi REST w usłudze GitHub. Aplikacja odczytuje informacje w formacie JSON i konwertuje kod JSON na obiekty języka C#. Konwertowanie z formatu JSON na obiekty języka C# jest nazywane deserializacją.
W samouczku pokazano, jak:
- Wysyłanie żądań HTTP.
- Deserializowanie odpowiedzi JSON.
- Konfigurowanie deserializacji za pomocą atrybutów.
Jeśli wolisz wykonać czynności opisane w ostatnim przykładzie na potrzeby tego samouczka, możesz go pobrać. Aby uzyskać instrukcje dotyczące pobierania, zobacz Przykłady i samouczki.
Wymagania wstępne
Tworzenie aplikacji klienckiej
Otwórz wiersz polecenia i utwórz nowy katalog dla aplikacji. Ustaw to jako bieżący katalog.
Wprowadź następujące polecenie w oknie konsoli:
dotnet new console --name WebAPIClientTo polecenie tworzy pliki początkowe dla podstawowej aplikacji "Hello World". Nazwa projektu to "WebAPIClient".
Przejdź do katalogu "WebAPIClient" i uruchom aplikację.
cd WebAPIClientdotnet rundotnet runautomatycznie uruchamiadotnet restore, aby przywrócić wszystkie zależności wymagane przez aplikację. Uruchamiane jest równieżdotnet buildw razie potrzeby. Powinieneś zobaczyć dane wyjściowe aplikacji"Hello, World!". W terminalu naciśnij Ctrl+C, aby zatrzymać aplikację.
Tworzenie żądań HTTP
Ta aplikacja wywołuje interfejs API GitHub , aby uzyskać informacje o projektach pod zwierzchnictwem .NET Foundation . Punkt końcowy jest https://api.github.com/orgs/dotnet/repos. Aby pobrać informacje, wysyła żądanie HTTP GET. Przeglądarki wysyłają również żądania HTTP GET, aby można było wkleić ten adres URL na pasku adresu przeglądarki, aby zobaczyć, jakie informacje będą odbierane i przetwarzane.
Użyj klasy HttpClient, aby wysyłać żądania HTTP. HttpClient obsługuje tylko metody asynchroniczne dla długotrwałych interfejsów API. Dlatego poniższe kroki umożliwiają utworzenie metody asynchronicznej i wywołanie jej z metody Main.
Otwórz plik
Program.csw katalogu projektu i zastąp jego zawartość następującym kodem:await ProcessRepositoriesAsync(); static async Task ProcessRepositoriesAsync(HttpClient client) { }Ten kod:
- Zastępuje instrukcję
Console.WriteLinewywołaniemProcessRepositoriesAsyncwykorzystującym słowo kluczoweawait. - Definiuje pustą metodę
ProcessRepositoriesAsync.
- Zastępuje instrukcję
W klasie
Programużyj HttpClient do obsługi żądań i odpowiedzi, zastępując zawartość następującym kodem C#.using System.Net.Http.Headers; using HttpClient client = new(); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/vnd.github.v3+json")); client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter"); await ProcessRepositoriesAsync(client); static async Task ProcessRepositoriesAsync(HttpClient client) { }Ten kod:
- Konfiguruje nagłówki HTTP dla wszystkich żądań:
- Nagłówek
Acceptakceptujący odpowiedzi JSON - Nagłówek
User-Agent. Te nagłówki są sprawdzane przez kod serwera GitHub i są niezbędne do pobrania informacji z usługi GitHub.
- Nagłówek
- Konfiguruje nagłówki HTTP dla wszystkich żądań:
W metodzie
ProcessRepositoriesAsyncwywołaj punkt końcowy usługi GitHub, który zwraca listę wszystkich repozytoriów w organizacji platformy .NET Foundation:static async Task ProcessRepositoriesAsync(HttpClient client) { var json = await client.GetStringAsync( "https://api.github.com/orgs/dotnet/repos"); Console.Write(json); }Ten kod:
- Oczekuje na zadanie zwrócone z wywołania metody HttpClient.GetStringAsync(String). Ta metoda wysyła żądanie HTTP GET do określonego adresu URI. Treść odpowiedzi jest zwracana jako String, która jest dostępna po zakończeniu zadania.
- Ciąg odpowiedzi
jsonjest wypisywany na konsolę.
Skompiluj aplikację i uruchom ją.
dotnet runNie ma ostrzeżenia dotyczącego kompilacji, ponieważ
ProcessRepositoriesAsynczawiera teraz operatorawait. Dane wyjściowe to rozległe wyświetlenie tekstu JSON.
Deserializowanie wyniku JSON
Poniższe kroki upraszczają podejście do pobierania danych i ich przetwarzania. Użyjesz GetFromJsonAsync metody rozszerzenia, która jest częścią 📦 pakietu NuGet System.Net.Http.Json , aby pobrać i deserializować wyniki JSON do obiektów.
Utwórz plik o nazwie Repository.cs i dodaj następujący kod:
public record class Repository(string Name);Powyższy kod definiuje klasę reprezentującą obiekt JSON zwrócony z interfejsu API usługi GitHub. Ta klasa służy do wyświetlania listy nazw repozytoriów.
Kod JSON obiektu repozytorium zawiera dziesiątki właściwości, ale tylko właściwość
Namezostanie zdeserializowana. Serializator automatycznie ignoruje właściwości JSON, dla których w klasie docelowej nie ma dopasowania. Ta funkcja ułatwia tworzenie typów, które działają tylko z podzbiorem pól w dużym pakiecie JSON.GetFromJsonAsyncMimo że metoda używana w następnym punkcie ma korzyść z uwzględniania wielkości liter, jeśli chodzi o nazwy właściwości, konwencja języka C# polega na wielką literę nazw właściwości.HttpClientJsonExtensions.GetFromJsonAsync Użyj metody , aby pobrać i przekonwertować kod JSON na obiekty języka C#. Zastąp wywołanie GetStringAsync(String) w metodzie
ProcessRepositoriesAsyncnastępującymi wierszami:var repositories = await client.GetFromJsonAsync<List<Repository>>("https://api.github.com/orgs/dotnet/repos");Zaktualizowany kod zastępuje GetStringAsync(String)HttpClientJsonExtensions.GetFromJsonAsync.
Pierwszym argumentem
GetFromJsonAsyncmetodyawaitjest wyrażenie.awaitwyrażenia mogą pojawiać się niemal wszędzie w kodzie, mimo że do tej pory widziałeś je tylko jako część instrukcji przypisania. Następny parametrrequestUrijest opcjonalny i nie musi być podany, jeśli został już określony podczas tworzeniaclientobiektu. Nie podanoclientobiektu z identyfikatorem URI do wysłania żądania, więc teraz określono identyfikator URI. Ostatni opcjonalny parametrCancellationTokenzostanie pominięty we fragmencie kodu.Metoda
GetFromJsonAsyncjest ogólna, co oznacza, że należy podać argumenty typu dla tego rodzaju obiektów, które powinny zostać utworzone na podstawie pobranego tekstu JSON. W tym przykładzie deserializujesz doList<Repository>, co jest innym ogólnym obiektem, czyli System.Collections.Generic.List<T>. KlasaList<T>przechowuje kolekcję obiektów. Argument typu deklaruje typ obiektów przechowywanych wList<T>. Typ argumentu to zapisRepository, ponieważ tekst JSON reprezentuje kolekcję obiektów repozytorium.Dodaj kod, aby wyświetlić nazwę każdego repozytorium. Zastąp linie, które brzmią:
Console.Write(json);z następującym kodem:
foreach (var repo in repositories ?? Enumerable.Empty<Repository>()) Console.WriteLine(repo.Name);W górnej części pliku powinny znajdować się następujące dyrektywy
using:using System.Net.Http.Headers; using System.Net.Http.Json;Uruchom aplikację.
dotnet runDane wyjściowe to lista nazw repozytoriów, które są częścią programu .NET Foundation.
Refaktoryzacja kodu
Metoda ProcessRepositoriesAsync może wykonywać asynchroniczne działanie i zwracać kolekcję repozytoriów. Zmień tę metodę, aby zwracała Task<List<Repository>>. Przenieś kod, który wypisuje na konsolę, w pobliże miejsca wywołania.
Zmień sygnaturę
ProcessRepositoriesAsync, aby zwrócić zadanie, którego wynikiem jest lista obiektówRepository:static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)Zwróć repozytoria po przetworzeniu odpowiedzi JSON:
var repositories = await client.GetFromJsonAsync<List<Repository>>("https://api.github.com/orgs/dotnet/repos"); return repositories ?? new();Kompilator generuje obiekt
Task<T>dla wartości zwracanej, ponieważ ta metoda została oznaczona jakoasync.Zmodyfikuj plik Program.cs, zastępując wywołanie
ProcessRepositoriesAsyncnastępującym kodem, aby przechwycić wyniki i zapisać każdą nazwę repozytorium do konsoli.var repositories = await ProcessRepositoriesAsync(client); foreach (var repo in repositories) Console.WriteLine(repo.Name);Uruchom aplikację.
Dane wyjściowe są takie same.
Deserializowanie większej liczby właściwości
W poniższych krokach rozszerzymy kod do przetwarzania większej liczby właściwości z ładunku JSON zwróconego przez interfejs API usługi GitHub. Prawdopodobnie nie trzeba przetwarzać każdej właściwości, ale dodanie kilku demonstruje dodatkowe funkcje języka C#.
Zastąp zawartość
Repositoryklasy następującąrecorddefinicją. Upewnij się, że zaimportujeszSystem.Text.Json.Serializationprzestrzeń nazw i zastosujesz[JsonPropertyName]atrybut, aby jawnie mapować pola JSON na właściwości C#.using System.Text.Json.Serialization; public record class Repository( string Name, string Description, [property: JsonPropertyName("html_url")] Uri GitHubHomeUrl, Uri Homepage, int Watchers, [property: JsonPropertyName("pushed_at")] DateTime LastPushUtc );Typy Uri i
intmają wbudowaną funkcję konwersji na i z reprezentacji ciągu. Do deserializacji z formatu ciągu JSON do tych typów docelowych nie jest potrzebny dodatkowy kod. Jeśli pakiet JSON zawiera dane, które nie są konwertowane na typ docelowy, akcja serializacji zgłasza wyjątek.JSON często używa
lowercaselubsnake_casedla nazw właściwości. Pola takie jakhtml_urlipushed_atnie są zgodne z konwencjami nazewnictwa PascalCase języka C#. Użycie[JsonPropertyName]zapewnia, że te klucze JSON są prawidłowo powiązane z odpowiednimi właściwościami języka C#, nawet jeśli ich nazwy różnią się literami lub zawierają podkreślenia. Takie podejście gwarantuje przewidywalną i stabilną deserializację, jednocześnie wspierając nazwy właściwości PascalCase w języku C#. Ponadto metodaGetFromJsonAsyncjestcase-insensitivew przypadku dopasowywania nazw właściwości, więc dalsza konwersja nie jest konieczna.Zaktualizuj pętlę
foreachw pliku Program.cs, aby wyświetlić wartości właściwości:foreach (var repo in repositories) { Console.WriteLine($"Name: {repo.Name}"); Console.WriteLine($"Homepage: {repo.Homepage}"); Console.WriteLine($"GitHub: {repo.GitHubHomeUrl}"); Console.WriteLine($"Description: {repo.Description}"); Console.WriteLine($"Watchers: {repo.Watchers:#,0}"); Console.WriteLine(); }Uruchom aplikację.
Lista zawiera teraz dodatkowe właściwości.
Dodaj właściwość daty
Data ostatniej operacji wypychania jest formatowana w ten sposób w odpowiedzi JSON:
2016-02-08T21:27:00Z
Ten format jest przeznaczony dla uniwersalnego czasu koordynowanego (UTC), dlatego wynikiem deserializacji jest wartość DateTime, której właściwość Kind jest Utc.
Aby uzyskać datę i godzinę reprezentowaną w strefie czasowej, musisz napisać niestandardową metodę konwersji.
W Repository.csdodaj właściwość reprezentującą datę i godzinę w formacie UTC oraz właściwość tylko do odczytu
LastPushzwracającą datę przekonwertowaną na czas lokalny, plik powinien wyglądać następująco:using System.Text.Json.Serialization; public record class Repository( string Name, string Description, [property: JsonPropertyName("html_url")] Uri GitHubHomeUrl, Uri Homepage, int Watchers, [property: JsonPropertyName("pushed_at")] DateTime LastPushUtc ) { public DateTime LastPush => LastPushUtc.ToLocalTime(); }Właściwość
LastPushjest zdefiniowana za pomocą elementu członkowskiego wyrażenia dla akcesoraget. Nie masetakcesora. Pominięcie akcesorasetjest jednym ze sposobów na zdefiniowanie właściwości tylko do odczytu w języku C#. (Tak, można utworzyć właściwości tylko do zapisu w języku C#, ale ich wartość jest ograniczona).Dodaj kolejną instrukcję danych wyjściowych w Program.cs: ponownie:
Console.WriteLine($"Last push: {repo.LastPush}");Kompletna aplikacja powinna przypominać następujący plik Program.cs:
using System.Net.Http.Headers; using System.Net.Http.Json; using HttpClient client = new(); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/vnd.github.v3+json")); client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter"); var repositories = await ProcessRepositoriesAsync(client); foreach (var repo in repositories) { Console.WriteLine($"Name: {repo.Name}"); Console.WriteLine($"Homepage: {repo.Homepage}"); Console.WriteLine($"GitHub: {repo.GitHubHomeUrl}"); Console.WriteLine($"Description: {repo.Description}"); Console.WriteLine($"Watchers: {repo.Watchers:#,0}"); Console.WriteLine($"{repo.LastPush}"); Console.WriteLine(); } static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client) { var repositories = await client.GetFromJsonAsync<List<Repository>>("https://api.github.com/orgs/dotnet/repos"); return repositories ?? new List<Repository>(); }Uruchom aplikację.
Dane wyjściowe obejmują datę i godzinę ostatniego wypchnięcia do każdego repozytorium.
Następne kroki
W tym samouczku stworzyłeś aplikację, która generuje zapytania sieciowe i przetwarza wyniki. Twoja wersja aplikacji powinna być teraz zgodna z ukończonym przykładem.
Dowiedz się więcej o konfigurowaniu serializacji JSON w Jak serializować i deserializować JSON na platformie .NET.