C#
- Tratando Json com o namespace System.Text.Json
![]() |
Hoje veremos como usar alguns recursos da biblioteca System.Text.Json para trabalhar com JSON. |
Trabalhar com o formato JSON atualmente é uma tarefa bem comum, e, para isso existem muitas bibliotecas que podem ser usadas na plataforma .NET; talvez as mais conhecidas sejam Newtonsoft.Json e a sua evolução : Json.NET.
A partir da versão 3.0 da plataforma .NET a Microsoft apresentou a biblioteca System.Text.Json como uma alternativa para trabalhar com JSON, e, que se propõe a ter um melhor desempenho.
Dessa forma, o namespace System.Text.Json fornece tipos de alto desempenho e baixa alocação de memória que serializam objetos para texto JavaScript Object Notation (JSON) e desserializam texto JSON para objetos, com suporte UTF-8 integrado.
Este namespace também fornece tipos para ler e gravar texto JSON codificado como UTF-8 e para criar um modelo de objeto de documento (DOM) na memória, que é somente leitura, para acesso aleatório dos elementos JSON em uma visualização estruturada dos dados.
As principais classes desta biblioteca são:
Provavelmente as tarefas mais realizadas com JSON sejam a serialização e desserialização.
Serializando e Desserializando JSON
1- Serializando JSON
Podemos serializar JSON usando qualquer uma das três classes apresentadas acima:
O método Serialize da classe JsonSerializer (JsonSerializer.Serialize) , talvez seja a forma mais simples de serializar JSON, e converte o valor de um tipo especificado em uma string JSON. O método possui diversas sobrecargas.
Obs: Nos exemplos estou usando os novos recursos Top Level Statement e record do C# 9.
Exemplo:
using System; using System.Text.Json; var usuario = new Usuario("Macoratti", "Programador", new Nascimento(30,11,1957)); var usuarioSerializado = JsonSerializer.Serialize(usuario); Console.WriteLine($" Usuario serializado = \n {usuarioSerializado} \n"); record Nascimento(int dia, int mes, int ano); |
Resultado:
2- Desserializando JSON
A desserialização pode ser feita também usando uma das 3 classes apresentadas.
A forma mais simples e direta é usar o método Deserialize da classe JsonSerializer.
O método Deserialize da classe JsonSerializer , possui várias sobrecargas, e no exemplo usado estamos o método analisa o texto que representa um único valor JSON em uma instância de um tipo especificado.
using System; using System.Text.Json;
string json = "{\"Nome\":\"Macoratti\",\"Cargo\":\"Programador\"," + var usuario = JsonSerializer.Deserialize<Usuario>(json); Console.WriteLine(usuario); Console.WriteLine(usuario.Nome); record Nascimento(int dia, int mes, int ano); |
Resultado:
Nota: Para desserializar a partir do formato UTF-8, utilize a sobrecarga do método JsonSerializer.Deserialize que usa um ReadOnlySpan<byte> ou um Utf8JsonReader.
Analisando JSON
O método Parse da classe JsonDocument analisa um stream como dados codificados em UTF-8 que representam um único valor JSON em um JsonDocument. O stream é lido até o fim.
using System;
using System.Text.Json;
string dados = " [ {\"nome\": \"Macoratti\", \"cargo\": \"Analista\"}, " +
"{\"nome\": \"Miriam\", \"cargo\": \"Secretária\"} ]";
using JsonDocument doc = JsonDocument.Parse(dados);
JsonElement root = doc.RootElement;
Console.WriteLine(root);
var u1 = root[0];
var u2 = root[1];
Console.WriteLine($"{u1}");
Console.WriteLine($"{u2}\n");
Console.WriteLine(u1.GetProperty("nome"));
Console.WriteLine(u1.GetProperty("cargo"));
Console.WriteLine(u2.GetProperty("nome"));
Console.WriteLine(u2.GetProperty("cargo"));
Console.ReadLine();
|
No exemplo acima a propriedade RootElement obtém o elemento raiz do documento JSON e o operador [] obtém o primeiro e o segundo subelementos do documento JSON. Para obter as propriedades de um elemento usamos o método GetProperty.
Resultado:
Criando um objeto JSON
A classe Utf8JsonWriter possui métodos que permitem gravar o texto sequencialmente sem cache e, por padrão, segue a RFC JSON, com exceção da gravação de comentários.
Um método que tenta gravar um JSON inválido quando a validação é habilitada gera um InvalidOperationException com uma mensagem de erro específica de contexto.
Para poder formatar a saída com indentação e espaço em branco, para ignorar a validação ou para personalizar o comportamento de escape, você tem que criar uma instância da struct JsonWriterOptions e passá-la para o gravador.
Exemplo: Criando um objeto JSON
using System;
using System.IO;
using System.Text.Json;
using System.Text;
using var ms = new MemoryStream();
using var writer = new Utf8JsonWriter(ms);
writer.WriteStartObject();
writer.WriteString("nome", "Macoratti");
writer.WriteString("cargo", "Programador");
writer.WriteNumber("idade", 54);
writer.WriteEndObject();
writer.Flush();
string json = Encoding.UTF8.GetString(ms.ToArray());
Console.WriteLine("Objeto JSON criado");
Console.WriteLine(json);
Console.ReadLine();
|
Resultado:
Podemos definir a opção Indented como true para formatar a saída JSON.
No exemplo abaixo estamos gerando o arquivo funcionarios.json na pasta c:\dados\json:
using System;
using System.IO;
using System.Text.Json;
var dados = " [ {\"nome\": \"Macoratti\", \"cargo\": \"Analista\"}, " +
"{\"nome\": \"Miriam\", \"cargo\": \"Secretária\"} ]";
JsonDocument jdoc = JsonDocument.Parse(dados);
var nomeArquivo = @"c:/dados/json/funcionarios.json";
using FileStream fs = File.OpenWrite(nomeArquivo);
using var writer = new Utf8JsonWriter(fs,
new JsonWriterOptions { Indented = true });
jdoc.WriteTo(writer);
Console.WriteLine($"Arquivo {nomeArquivo} criado com sucesso");
Console.ReadLine();
|
Lendo arquivo JSON
A classe Utf8JsonReader possui métodos para processar um texto sequencialmente sem cache e, por padrão, segue estritamente a RFC JSON.
Quando o Utf8JsonReader encontra um JSON inválido, ele gera uma JsonException com informações básicas de erro, como número de linha e posição de byte na linha.
Como esse tipo é uma struct de referência, ele não dá suporte diretamente a Async. No entanto, ele fornece suporte para reentrância a fim de ler dados incompletos e continuar lendo quando mais dados forem apresentados.
Para poder definir a profundidade máxima ao ler ou permitir comentários ignorados, crie uma instância do JsonReaderOptions e passe-a para o leitor.
Exemplo: Neste exemplo estamos lendo o arquivo funcionarios.json no formato:
[
{
"nome": "Macoratti",
"cargo": "Programador"
},
{
"nome": "Jefferson",
"cargo": "Engenheiro"
}
]
|
using System; using System.IO; using System.Text.Json; var nomeArquivo = @"c:/dados/json/funcionarios.json"; byte[] data = File.ReadAllBytes(nomeArquivo); Utf8JsonReader reader = new Utf8JsonReader(data); while (reader.Read()) } |
No exemplo, lemos dados JSON de um arquivo com Utf8JsonReader que fornece uma API de baixo nível para leitura de dados JSON.
Resultado:
Pegue o código do
projeto aqui:
Json.zip
Porque um menino nos nasceu, um filho se nos deu, e o principado está sobre os seus ombros, e se chamará o seu nome: Maravilhoso, Conselheiro, Deus Forte, Pai da Eternidade, Príncipe da Paz.
Referências:
C# - Obtendo a data e a hora por TimeZone
C# - O Struct Guid - Macoratti.net
C# - Checando Null de uma forma mais elegante e concisa
DateTime - Macoratti.net
Null o que é isso ? - Macoratti.net
Formatação de data e hora para uma cultura ...
C# - Calculando a diferença entre duas datas
NET - Padrão de Projeto - Null Object Pattern - Macoratti
C# - Fundamentos : Definindo DateTime como Null ...
C# - Os tipos Nullable (Tipos Anuláveis) - Macoratti.net