Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você 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 em C# é conhecida como desserialização.
O tutorial mostra como:
- Enviar solicitações HTTP.
- Desserializar respostas JSON.
- Configure a desserialização com atributos.
Se você preferir acompanhar o exemplo final deste tutorial, poderá baixá-lo. Para obter instruções de download, consulte Exemplos e Tutoriais.
Pré-requisitos
- O .NET SDK mais recente
- Editor do Visual Studio Code
- O DevKit C#
Criar o aplicativo cliente
Abra um prompt de comando e crie um novo diretório para seu aplicativo. Faça disso o diretório atual.
Insira o seguinte comando em uma janela do console:
dotnet new console --name WebAPIClientEsse comando cria os arquivos indispiratórios para um aplicativo básico "Olá, Mundo". O nome do projeto é "WebAPIClient".
Navegue até o diretório "WebAPIClient" e execute o aplicativo.
cd WebAPIClientdotnet rundotnet runé executadodotnet restoreautomaticamente para restaurar as dependências de que o aplicativo precisa. Ele também é executadodotnet buildse necessário. Você deve ver a saída"Hello, World!"do aplicativo. No terminal, pressione Ctrl+C para interromper o aplicativo.
Fazer solicitações HTTP
Esse aplicativo chama a API do GitHub para obter informações sobre os projetos no guarda-chuva do .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 essa URL na barra de endereços do navegador para ver quais informações você receberá e processará.
Use a HttpClient classe para fazer solicitações HTTP. HttpClient dá suporte apenas a 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 do método Main.
Abra o
Program.csarquivo no diretório do projeto e substitua seu conteúdo pelo seguinte:await ProcessRepositoriesAsync(); static async Task ProcessRepositoriesAsync(HttpClient client) { }Este código:
- Substitui a
Console.WriteLineinstrução por uma chamada queProcessRepositoriesAsyncusa aawaitpalavra-chave. - Define um método vazio
ProcessRepositoriesAsync.
- Substitui a
ProgramNa classe, use um HttpClient para lidar com solicitações e respostas, substituindo o conteúdo pelo C#a seguir.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
Acceptcabeçalho para 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
- Configura cabeçalhos HTTP para todas as solicitações:
ProcessRepositoriesAsyncNo método, chame o ponto de extremidade do GitHub que retorna uma lista de todos os repositórios na organização do .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 do método de chamada 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 está disponível quando a tarefa é concluída.
- A cadeia de caracteres de
jsonresposta é impressa no console.
Crie o aplicativo e execute-o.
dotnet runNão há nenhum aviso de build porque o
ProcessRepositoriesAsyncagora contém umawaitoperador. A saída é uma exibição longa do 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 de um objeto de repositório contém dezenas de propriedades, mas somente a
Namepropriedade será 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 apenas com um subconjunto de campos em um pacote JSON grande.Embora o
GetFromJsonAsyncmétodo que você usará no próximo ponto tenha o benefício de não diferenciar maiúsculas de minúsculas quando se trata de nomes de propriedade, a convenção C# é para capitalizar a primeira letra de nomes de propriedade.Use o HttpClientJsonExtensions.GetFromJsonAsync método para buscar e converter JSON em objetos C#. Substitua a chamada no GetStringAsync(String)
ProcessRepositoriesAsyncmétodo pelas 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 a ser
GetFromJsonAsyncmétodo é uma expressãoawait.awaitas expressões podem aparecer em praticamente qualquer lugar em seu código, mesmo que até agora, você as tenha visto apenas como parte de uma instrução de atribuição. O próximo parâmetro érequestUriopcional e não precisa ser fornecido se já tiver sido especificado ao criar oclientobjeto. Você não forneceu o objeto com oclientURI para o qual enviar a solicitação, portanto, você especificou o URI agora. O último parâmetro opcional, oCancellationTokené omitido no snippet 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>. AList<T>classe armazena uma coleção de objetos. O argumento type declara o tipo de objetos armazenados noList<T>. O argumento de tipo é seuRepositoryregistro, pois 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 leem:
Console.Write(json);com o seguinte código:
foreach (var repo in repositories ?? Enumerable.Empty<Repository>()) Console.WriteLine(repo.Name);As seguintes
usingdiretivas devem 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.
Refatorar o código
O ProcessRepositoriesAsync método pode fazer o trabalho assíncrono e retornar uma coleção de 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 para
ProcessRepositoriesAsyncretornar 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
Task<T>objeto para o valor retornado porque você marcou esse método comoasync.Modifique o arquivo Program.cs , substituindo a chamada pelo
ProcessRepositoriesAsyncseguinte para capturar os resultados e gravar cada nome do 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 do conteúdo JSON retornado pela API do GitHub. Você provavelmente não precisará processar todas as propriedades, mas adicionar algumas demonstra alguns recursos adicionais do C#.
Substitua o conteúdo da
Repositoryclasse pela definição a seguirrecord. 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 Uri tipos e os
inttipos têm funcionalidade interna para converter de e para a 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 gerará uma exceção.O JSON geralmente usa
lowercaseousnake_casepara nomes de propriedade. Campos comohtml_urlepushed_atnão seguem as convenções de nomenclatura do C# PascalCase. O uso[JsonPropertyName]garante que essas chaves JSON estejam corretamente associadas às respectivas propriedades C#correspondentes, mesmo quando seus nomes diferem no caso ou contêm sublinhados. Essa abordagem garante a desserialização previsível e estável, permitindo nomes de propriedade PascalCase em C#. Além disso, oGetFromJsonAsyncmétodo écase-insensitiveao fazer correspondência de nomes de propriedade, portanto, nenhuma conversão adicional é necessária.Atualize o
foreachloop no arquivo Program.cs para exibir os valores da 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 date
A data da última operação de push é formatada dessa forma na resposta JSON:
2016-02-08T21:27:00Z
Esse formato é para UTC (Tempo Universal Coordenado), portanto, o resultado da desserialização é um DateTime valor cuja Kind propriedade é Utc.
Para obter uma data e hora representadas em seu fuso horário, você precisa escrever um método de conversão personalizado.
Em Repository.cs, adicione uma propriedade para a representação UTC da data e hora e uma propriedade somente leitura
LastPushque retorna a data convertida em hora local, o arquivo deve ser semelhante ao seguinte: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
LastPushpropriedade é definida usando um membro com corpo de expressão para ogetacessador. Não há acessadorset. Omitir osetacessador é uma maneira de definir uma propriedade somente leitura em C#. (Sim, você pode criar propriedades 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 de 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 push para cada repositório.
Próximas etapas
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.
Saiba mais sobre como configurar a serialização JSON em Como serializar e desserializar (marshal e unmarshal) JSON no .NET.