Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este tutorial cria um aplicativo que emite solicitações HTTP para um serviço REST no GitHub. O aplicativo lê informações no formato JSON e converte o JSON em objetos C#. A conversão de objetos JSON para objetos C# é conhecida como desserialização.
O tutorial mostra como:
- Enviar solicitações HTTP.
- Desserialize respostas JSON.
- Configure a desserialização utilizando atributos.
Se preferir acompanhar com a amostra final deste tutorial, pode descarregá-la. Para obter instruções de download, consulte Exemplos e Tutoriais.
Pré-requisitos
- O mais recente SDK do .NET
- Editor de código do Visual Studio
- O Kit de Desenvolvimento C#
Criar o aplicativo cliente
Abra um prompt de comando e crie um novo diretório para seu aplicativo. Defina isso como o diretório atual.
Digite o seguinte comando em uma janela do console:
dotnet new console --name WebAPIClientEste comando cria os arquivos iniciais para um aplicativo básico "Hello World". O nome do projeto é "WebAPIClient".
Navegue até o diretório "WebAPIClient" e execute o aplicativo.
cd WebAPIClientdotnet rundotnet runexecuta automaticamentedotnet restorepara restaurar quaisquer dependências de que o aplicativo precisa. Ele também executadotnet buildse necessário. Você deve ver a saída do aplicativo"Hello, World!". No terminal, pressione Ctrl+C para parar o aplicativo.
Fazer solicitações HTTP
Este aplicativo chama a API do GitHub para obter informações sobre os projetos sob a égide da .NET Foundation . O ponto de extremidade é https://api.github.com/orgs/dotnet/repos. Para recuperar informações, ele faz uma solicitação HTTP GET. Os navegadores também fazem solicitações HTTP GET, para que você possa colar esse URL na barra de endereço do navegador para ver quais informações você receberá e processará.
Use a classe HttpClient para fazer solicitações HTTP. HttpClient suporta apenas métodos assíncronos para suas APIs de longa execução. Portanto, as etapas a seguir criam um método assíncrono e o chamam a partir do método Main.
Abra o arquivo
Program.csno diretório do projeto e substitua seu conteúdo pelo seguinte:await ProcessRepositoriesAsync(); static async Task ProcessRepositoriesAsync(HttpClient client) { }Este código:
- Substitui a instrução
Console.WriteLinepor uma chamada paraProcessRepositoriesAsyncque usa a palavra-chaveawait. - Define um método
ProcessRepositoriesAsyncvazio.
- Substitui a instrução
Na classe
Program, use um HttpClient para manipular solicitações e respostas, substituindo o conteúdo pelo seguinte código 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) { }Este código:
- Configura cabeçalhos HTTP para todas as solicitações:
- Um cabeçalho
Acceptpara aceitar respostas JSON - Um
User-Agentcabeçalho. Esses cabeçalhos são verificados pelo código do servidor GitHub e são necessários para recuperar informações do GitHub.
- Um cabeçalho
- Configura cabeçalhos HTTP para todas as solicitações:
No método
ProcessRepositoriesAsync, chame o endpoint do GitHub que retorna uma lista de todos os repositórios dentro da organização .NET Foundation:static async Task ProcessRepositoriesAsync(HttpClient client) { var json = await client.GetStringAsync( "https://api.github.com/orgs/dotnet/repos"); Console.Write(json); }Este código:
- Aguarda a tarefa retornada pela chamada do método HttpClient.GetStringAsync(String). Esse método envia uma solicitação HTTP GET para o URI especificado. O corpo da resposta é retornado como um String, que fica disponível quando a tarefa é concluída.
- A cadeia de caracteres de resposta
jsoné impressa no console.
Crie o aplicativo e execute-o.
dotnet runNão há nenhum aviso de compilação porque o
ProcessRepositoriesAsyncagora contém um operadorawait. A saída é uma longa exibição de texto JSON.
Desserializar o resultado JSON
As etapas a seguir simplificam a abordagem para buscar os dados e processá-los. Você usará o GetFromJsonAsync método de extensão que faz parte do 📦 pacote NuGet System.Net.Http.Json para buscar e desserializar os resultados JSON em objetos.
Crie um arquivo chamado Repository.cs e adicione o seguinte código:
public record class Repository(string Name);O código anterior define uma classe para representar o objeto JSON retornado da API do GitHub. Você usará essa classe para exibir uma lista de nomes de repositório.
O JSON para um objeto de repositório contém dezenas de propriedades, mas apenas a propriedade
Nameserá desserializada. O serializador ignora automaticamente as propriedades JSON para as quais não há correspondência na classe de destino. Esse recurso facilita a criação de tipos que funcionam com apenas um subconjunto de campos em um pacote JSON grande.Embora o
GetFromJsonAsyncmétodo que você usará no próximo ponto tenha a vantagem de não diferenciar maiúsculas de minúsculas quando se trata de nomes de propriedade, a convenção C# é capitalizar a primeira letra dos nomes de propriedade.Use o HttpClientJsonExtensions.GetFromJsonAsync método para buscar e converter JSON em objetos C#. Substitua a chamada para GetStringAsync(String) no método
ProcessRepositoriesAsyncpelas seguintes linhas:var repositories = await client.GetFromJsonAsync<List<Repository>>("https://api.github.com/orgs/dotnet/repos");O código atualizado substitui GetStringAsync(String) por HttpClientJsonExtensions.GetFromJsonAsync.
O primeiro argumento para o
GetFromJsonAsyncmétodo é umaawaitexpressão.awaitexpressões podem aparecer em praticamente qualquer lugar do seu código, embora até agora, você só as tenha visto como parte de uma instrução de atribuição. O próximo parâmetrorequestUrié opcional e não precisa ser fornecido se já tiver sido especificado ao criar oclientobjeto. Você não forneceu aoclientobjeto o URI para enviar a solicitação, então especificou o URI agora. O último parâmetro opcional, oCancellationTokené omitido no trecho de código.O
GetFromJsonAsyncmétodo é genérico, o que significa que você fornece argumentos de tipo para que tipo de objetos devem ser criados a partir do texto JSON buscado. Neste exemplo, você está desserializando para umList<Repository>, que é outro objeto genérico, um System.Collections.Generic.List<T>. A classeList<T>armazena uma coleção de objetos. O argumento type declara o tipo de objetos armazenados noList<T>. O argumento type é seu registroRepository, porque o texto JSON representa uma coleção de objetos de repositório.Adicione código para exibir o nome de cada repositório. Substitua as linhas que dizem:
Console.Write(json);com o seguinte código:
foreach (var repo in repositories ?? Enumerable.Empty<Repository>()) Console.WriteLine(repo.Name);As seguintes diretivas
usingdevem estar presentes na parte superior do arquivo:using System.Net.Http.Headers; using System.Net.Http.Json;Execute o aplicativo.
dotnet runA saída é uma lista dos nomes dos repositórios que fazem parte do .NET Foundation.
Refatore o código
O método ProcessRepositoriesAsync pode fazer o trabalho assíncrono e retornar uma coleção dos repositórios. Altere esse método para retornar Task<List<Repository>>e mova o código que grava no console perto de seu chamador.
Altere a assinatura de
ProcessRepositoriesAsyncpara retornar uma tarefa cujo resultado é uma lista deRepositoryobjetos:static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)Retorne os repositórios depois de processar a resposta JSON:
var repositories = await client.GetFromJsonAsync<List<Repository>>("https://api.github.com/orgs/dotnet/repos"); return repositories ?? new();O compilador gera o objeto
Task<T>para o valor de retorno porque você marcou esse método comoasync.Modifique o arquivo Program.cs, substituindo a chamada para
ProcessRepositoriesAsyncpelo seguinte para capturar os resultados e gravar cada nome de repositório no console.var repositories = await ProcessRepositoriesAsync(client); foreach (var repo in repositories) Console.WriteLine(repo.Name);Execute o aplicativo.
A saída é a mesma.
Desserializar mais propriedades
Nas etapas a seguir, estendemos o código para processar mais propriedades da carga JSON retornada pela API do GitHub. Você provavelmente não precisará processar todas as propriedades, mas adicionar algumas demonstra recursos adicionais do C#.
Substitua o
Repositoryconteúdo da classe pela seguinterecorddefinição. Certifique-se de importar oSystem.Text.Json.Serializationnamespace e aplicar o[JsonPropertyName]atributo para mapear campos JSON para propriedades C# explicitamente.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 );Os tipos Uri e
inttêm funcionalidade interna para converter de e para representação de cadeia de caracteres. Nenhum código extra é necessário para desserializar do formato de cadeia de caracteres JSON para esses tipos de destino. Se o pacote JSON contiver dados que não são convertidos em um tipo de destino, a ação de serialização lançará uma exceção.JSON geralmente usa
lowercaseousnake_casepara nomes de propriedade. Os campos tais comohtml_urlepushed_atnão seguem as convenções de nomenclatura C# PascalCase. A utilização de[JsonPropertyName]assegura que essas chaves JSON são corretamente vinculadas às propriedades C# correspondentes, mesmo quando seus nomes apresentam diferenças de maiúsculas e minúsculas ou contêm sublinhados. Essa abordagem garante uma desserialização previsível e estável, permitindo nomes de propriedade PascalCase em C#. Além disso, o métodoGetFromJsonAsyncé utilizado quando os nomes de propriedadecase-insensitivecorrespondem, portanto, não é necessária nenhuma conversão adicional.Atualize o loop de
foreachno arquivo Program.cs para exibir os valores de propriedade: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(); }Execute o aplicativo.
A lista agora inclui as propriedades adicionais.
Adicionar uma propriedade de data
A data da última operação de push é formatada desta forma na resposta JSON:
2016-02-08T21:27:00Z
Este formato é para Tempo Universal Coordenado (UTC), portanto, o resultado da desserialização é um valor de DateTime cuja propriedade Kind é Utc.
Para obter uma data e hora representadas no seu fuso horário, você precisa escrever um método de conversão personalizado.
No Repository.cs, adicione uma propriedade para a representação da data e hora em UTC e uma propriedade somente leitura
LastPushque retorna a data convertida para a hora local, o arquivo deve ter a seguinte aparência: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(); }A propriedade
LastPushé definida usando um de membro com corpo de expressão para o acessadorget. Não há acessórioset. Omitir o acessador deseté uma maneira de definir uma propriedade somente leitura em C#. (Sim, você pode criar propriedades de somente gravação em C#, mas seu valor é limitado.)Adicione outra instrução de saída em Program.cs: novamente:
Console.WriteLine($"Last push: {repo.LastPush}");O aplicativo completo deve ser semelhante ao seguinte arquivo 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>(); }Execute o aplicativo.
A saída inclui a data e a hora do último envio para cada repositório.
Próximos passos
Neste tutorial, você criou um aplicativo que faz solicitações da Web e analisa os resultados. Sua versão do aplicativo agora deve corresponder ao exemplo concluído.
Descubra como configurar a serialização JSON no e como serializar e desserializar (marshal e unmarshal) JSON no .NET.