Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In deze zelfstudie wordt een app gebouwd waarmee HTTP-aanvragen worden verzonden naar een REST-service op GitHub. De app leest informatie in JSON-indeling en converteert de JSON naar C#-objecten. Converteren van JSON naar C#-objecten wordt deserialisatie genoemd.
In de zelfstudie ziet u hoe u het volgende kunt doen:
- HTTP-aanvragen verzenden.
- JSON-antwoorden deserialiseren.
- Configureer deserialisatie met kenmerken.
Als u liever het laatste voorbeeld voor deze zelfstudie volgt, kunt u het downloaden. Zie voorbeelden en zelfstudiesvoor downloadinstructies.
Vereiste voorwaarden
- De nieuwste .NET SDK-
- Visual Studio Code-editor
- De C# DevKit
De client-app maken
Open een opdrachtprompt en maak een nieuwe map voor uw app. Maak dat de huidige map.
Voer de volgende opdracht in een consolevenster in:
dotnet new console --name WebAPIClientMet deze opdracht maakt u de startersbestanden voor een eenvoudige 'Hallo wereld'-app. De projectnaam is 'WebAPIClient'.
Navigeer naar de map WebAPIClient en voer de app uit.
cd WebAPIClientdotnet rundotnet runwordt automatisch uitgevoerddotnet restoreom afhankelijkheden te herstellen die de app nodig heeft. Het wordt ook uitgevoerddotnet buildindien nodig. U ziet nu de uitvoer"Hello, World!"van de app. Druk in de terminal op Ctrl+C om de app te stoppen.
HTTP-aanvragen maken
Met deze app wordt de GitHub-API aangeroepen voor informatie over de projecten onder de paraplu van .NET Foundation . Het eindpunt is https://api.github.com/orgs/dotnet/repos. Als u informatie wilt ophalen, wordt er een HTTP GET-aanvraag ingediend. Browsers maken ook HTTP GET-aanvragen, zodat u die URL in de adresbalk van uw browser kunt plakken om te zien welke informatie u ontvangt en verwerkt.
Gebruik de HttpClient klasse om HTTP-aanvragen te maken. HttpClient ondersteunt alleen asynchrone methoden voor de langlopende API's. Met de volgende stappen maakt u dus een asynchrone methode en roept u deze aan vanuit de Main-methode.
Open het
Program.csbestand in de projectmap en vervang de inhoud door het volgende:await ProcessRepositoriesAsync(); static async Task ProcessRepositoriesAsync(HttpClient client) { }Deze code:
- Vervangt de
Console.WriteLineinstructie door een aanroep naarProcessRepositoriesAsyncdie gebruikmaakt van hetawaittrefwoord. - Definieert een lege
ProcessRepositoriesAsyncmethode.
- Vervangt de
Gebruik in de
Programklasse een HttpClient om aanvragen en antwoorden te verwerken door de inhoud te vervangen door de volgende 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) { }Deze code:
- Hiermee stelt u HTTP-headers in voor alle aanvragen:
- Een
Acceptheader voor het accepteren van JSON-antwoorden - Een
User-Agentkoptekst. Deze headers worden gecontroleerd door de GitHub-servercode en zijn nodig om informatie op te halen uit GitHub.
- Een
- Hiermee stelt u HTTP-headers in voor alle aanvragen:
Roep in de
ProcessRepositoriesAsyncmethode het GitHub-eindpunt aan dat een lijst met alle opslagplaatsen retourneert onder de .NET Foundation-organisatie:static async Task ProcessRepositoriesAsync(HttpClient client) { var json = await client.GetStringAsync( "https://api.github.com/orgs/dotnet/repos"); Console.Write(json); }Deze code:
- Wacht op de taak die is geretourneerd door de aanroepmethode HttpClient.GetStringAsync(String) . Met deze methode wordt een HTTP GET-aanvraag verzonden naar de opgegeven URI. De hoofdtekst van het antwoord wordt geretourneerd als een String, die beschikbaar is wanneer de taak is voltooid.
- De antwoordtekenreeks
jsonwordt afgedrukt naar de console.
Bouw de app en voer deze uit.
dotnet runEr is geen buildwaarschuwing omdat de
ProcessRepositoriesAsyncoperator nu bevatawait. De uitvoer is een lange weergave van JSON-tekst.
Het JSON-resultaat deserialiseren
De volgende stappen vereenvoudigen de aanpak voor het ophalen van de gegevens en het verwerken ervan. U gebruikt de GetFromJsonAsync extensiemethode die deel uitmaakt van het 📦 NuGet-pakket System.Net.Http.Json om de JSON-resultaten in objecten op te halen en deserialiseren.
Maak een bestand met de naam Repository.cs en voeg de volgende code toe:
public record class Repository(string Name);De voorgaande code definieert een klasse die het JSON-object vertegenwoordigt dat wordt geretourneerd door de GitHub-API. U gebruikt deze klasse om een lijst met namen van opslagplaatsen weer te geven.
De JSON voor een opslagplaatsobject bevat tientallen eigenschappen, maar alleen de
Nameeigenschap wordt gedeserialiseerd. De serializer negeert automatisch JSON-eigenschappen waarvoor geen overeenkomst is in de doelklasse. Met deze functie kunt u eenvoudiger typen maken die alleen werken met een subset velden in een groot JSON-pakket.Hoewel de
GetFromJsonAsyncmethode die u in het volgende punt gaat gebruiken, een voordeel heeft dat het hoofdlettergevoelig is als het gaat om eigenschapsnamen, is de C#-conventie het hoofdlettergebruik van de eerste letter van eigenschapsnamen.Gebruik de HttpClientJsonExtensions.GetFromJsonAsync methode om JSON op te halen en te converteren naar C#-objecten. Vervang de aanroep in GetStringAsync(String) de
ProcessRepositoriesAsyncmethode door de volgende regels:var repositories = await client.GetFromJsonAsync<List<Repository>>("https://api.github.com/orgs/dotnet/repos");De bijgewerkte code vervangt door GetStringAsync(String)HttpClientJsonExtensions.GetFromJsonAsync.
Het eerste argument voor
GetFromJsonAsyncde methode is eenawaitexpressie.awaitexpressies kunnen bijna overal in uw code worden weergegeven, ook al hebt u deze tot nu toe alleen gezien als onderdeel van een toewijzingsinstructie. De volgende parameter isrequestUrioptioneel en hoeft niet te worden opgegeven als al is opgegeven bij het maken van hetclientobject. U hebt hetclientobject niet opgegeven met de URI waarnaar u een aanvraag wilt verzenden, dus u hebt de URI nu opgegeven. De laatste optionele parameter wordtCancellationTokenweggelaten in het codefragment.De
GetFromJsonAsyncmethode is algemeen. Dit betekent dat u typeargumenten opgeeft voor het soort objecten dat moet worden gemaakt op basis van de opgehaalde JSON-tekst. In dit voorbeeld gaat u deserialiseren naar eenList<Repository>, een ander algemeen object, een System.Collections.Generic.List<T>. In deList<T>klasse wordt een verzameling objecten opgeslagen. Het typeargument declareert het type objecten dat is opgeslagen in deList<T>. Het typeargument is uwRepositoryrecord, omdat de JSON-tekst een verzameling opslagplaatsobjecten vertegenwoordigt.Voeg code toe om de naam van elke opslagplaats weer te geven. Vervang de regels die worden gelezen:
Console.Write(json);met de volgende code:
foreach (var repo in repositories ?? Enumerable.Empty<Repository>()) Console.WriteLine(repo.Name);De volgende
usinginstructies moeten boven aan het bestand aanwezig zijn:using System.Net.Http.Headers; using System.Net.Http.Json;Voer de app uit.
dotnet runDe uitvoer is een lijst met de namen van de opslagplaatsen die deel uitmaken van de .NET Foundation.
De code herstructureren
De ProcessRepositoriesAsync methode kan het asynchrone werk uitvoeren en een verzameling van de opslagplaatsen retourneren. Wijzig deze methode om deze te retourneren Task<List<Repository>>en verplaats de code die naar de console schrijft in de buurt van de aanroeper.
Wijzig de handtekening van het retourneren van
ProcessRepositoriesAsynceen taak waarvan het resultaat een lijstRepositorymet objecten is:static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)Retourneert de opslagplaatsen na het verwerken van het JSON-antwoord:
var repositories = await client.GetFromJsonAsync<List<Repository>>("https://api.github.com/orgs/dotnet/repos"); return repositories ?? new();De compiler genereert het
Task<T>object voor de retourwaarde omdat u deze methode hebt gemarkeerd alsasync.Wijzig het Program.cs-bestand , waarbij u de aanroep vervangt door
ProcessRepositoriesAsynchet volgende om de resultaten vast te leggen en elke naam van de opslagplaats naar de console te schrijven.var repositories = await ProcessRepositoriesAsync(client); foreach (var repo in repositories) Console.WriteLine(repo.Name);Voer de app uit.
De uitvoer is hetzelfde.
Meer eigenschappen deserialiseren
In de volgende stappen breiden we de code uit om meer eigenschappen te verwerken van de JSON-nettolading die wordt geretourneerd door de GitHub-API. U hoeft waarschijnlijk niet elke eigenschap te verwerken, maar door er een paar toe te voegen, kunt u extra C#-functies demonstreren.
Vervang de inhoud van de
Repositoryklasse door de volgenderecorddefinitie. Zorg ervoor dat u deSystem.Text.Json.Serializationnaamruimte importeert en het[JsonPropertyName]kenmerk toepast om JSON-velden expliciet toe te wijzen aan C#-eigenschappen.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 );De Uri en
inttypen hebben ingebouwde functionaliteit om te converteren naar en van tekenreeksweergave. Er is geen extra code nodig om deserialiseren van JSON-tekenreeksindeling naar deze doeltypen. Als het JSON-pakket gegevens bevat die niet naar een doeltype worden geconverteerd, genereert de serialisatieactie een uitzondering.JSON gebruikt
lowercasevaak ofsnake_casevoor eigenschapsnamen. Velden zoalshtml_urlenpushed_atvolgen niet de PascalCase-naamconventies van C#. Het gebruik[JsonPropertyName]zorgt ervoor dat deze JSON-sleutels correct zijn gebonden aan de bijbehorende C#-eigenschappen, zelfs als hun namen verschillen in het geval of onderstrepingstekens bevatten. Deze aanpak garandeert voorspelbare en stabiele deserialisatie, terwijl PascalCase-eigenschapsnamen in C# worden toegestaan. Daarnaast isGetFromJsonAsyncdecase-insensitivemethode wanneer overeenkomende eigenschapsnamen worden gebruikt, zodat er geen verdere conversie nodig is.Werk de
foreachlus in het Program.cs bestand bij om de eigenschapswaarden weer te geven: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(); }Voer de app uit.
De lijst bevat nu de aanvullende eigenschappen.
Een datumeigenschap toevoegen
De datum van de laatste pushbewerking wordt op deze manier opgemaakt in het JSON-antwoord:
2016-02-08T21:27:00Z
Deze notatie is bedoeld voor Coordinated Universal Time (UTC), dus het resultaat van deserialisatie is een DateTime waarde waarvan Kind de eigenschap is Utc.
Als u een datum en tijd wilt ophalen die in uw tijdzone wordt weergegeven, moet u een aangepaste conversiemethode schrijven.
Voeg in Repository.cs een eigenschap toe voor de UTC-weergave van de datum en tijd en een alleen-lezen
LastPusheigenschap die de datum retourneert die wordt geconverteerd naar lokale tijd. Het bestand moet er als volgt uitzien: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(); }De
LastPusheigenschap wordt gedefinieerd met behulp van een expressie-lichaamslid voor degettoegangsfunctie. Er is geensettoegangsrechten. Het weglaten van desetaccessor is één manier om een alleen-lezen eigenschap in C# te definiëren. (Ja, u kunt eigenschappen voor alleen-schrijven maken in C#, maar hun waarde is beperkt.)Voeg nog een uitvoerinstructie toe in Program.cs: opnieuw:
Console.WriteLine($"Last push: {repo.LastPush}");De volledige app moet er ongeveer uitzien als het volgende Program.cs bestand:
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>(); }Voer de app uit.
De uitvoer bevat de datum en tijd van de laatste push naar elke opslagplaats.
Volgende stappen
In deze zelfstudie hebt u een app gemaakt waarmee webaanvragen worden gedaan en de resultaten worden geparseerd. Uw versie van de app moet nu overeenkomen met het voltooide voorbeeld.
Meer informatie over het configureren van JSON-serialisatie in JSON in .NET: serialiseren en deserialiseren (marshal en unmarshal).