C#: JSON e serialização

1. Noções básicas sobre o formato JSON

JSON (JavaScript Object Notation) é um formato leve de intercâmbio de dados que armazena e transmite dados estruturados como texto simples.

TEXT 📖 Somente leitura
{
  "name": "Zhang San",
  "age": 28,
  "isStudent": false,
  "hobbies": ["programming", "reading"],
  "address": {
    "city": "Beijing",
    "zip": "100000"
  }
}

2. Visão geral do System.Text.Json

System.Text.Json é uma biblioteca JSON de alto desempenho integrada ao .NET Core 3.0+, que não requer pacotes de terceiros. É recomendada em vez da Newtonsoft.Json.

CSHARP
using System.Text.Json;

3. Serialização: de objeto para JSON

JsonSerializer.Serialize() converte um objeto em uma string JSON.

▶ Exemplo

CSHARP
using System;
using System.Text.Json;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public bool IsStudent { get; set; }
}

class Program
{
    static void Main()
    {
        var person = new Person
        {
            Name = "Zhang San",
            Age = 28,
            IsStudent = false
        };
        string json = JsonSerializer.Serialize(person);
        Console.WriteLine(json);
    }
}
▶ Experimente
TEXT 📖 Somente leitura
{"Name":"Zhang San","Age":28,"IsStudent":false}

4. Deserialização: de JSON para objeto

JsonSerializer.Deserialize``<T>``() converte uma string JSON de volta em um objeto do tipo especificado.

▶ Exemplo

CSHARP
using System;
using System.Text.Json;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public bool IsStudent { get; set; }
}

class Program
{
    static void Main()
    {
        string json = @"{""Name"":""Zhang San"",""Age"":28,""IsStudent"":false}";
        Person person = JsonSerializer.Deserialize<Person>(json);
        Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
    }
}
▶ Experimente
TEXT 📖 Somente leitura
Name: Zhang San, Age: 28

5. Configuração do JsonSerializerOptions

Use JsonSerializerOptions para controlar o comportamento da serialização, como a política de nomenclatura, a indentação e a ignorância de valores nulos.

Opção Descrição
PropertyNamingPolicy Política de nomenclatura de propriedades, por exemplo, JsonNamingPolicy.CamelCase
WriteIndented Se a saída deve ser recuada para facilitar a leitura
IgnoreNullValues Se as propriedades com valor nulo devem ser ignoradas
PropertyNameCaseInsensitive Ignorar maiúsculas e minúsculas nos nomes das propriedades durante a desserialização

▶ Exemplo

CSHARP
using System;
using System.Text.Json;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; }
}

class Program
{
    static void Main()
    {
        var person = new Person
        {
            Name = "Zhang San",
            Age = 28,
            Email = null
        };

        var options = new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = true,
            IgnoreNullValues = true
        };

        string json = JsonSerializer.Serialize(person, options);
        Console.WriteLine(json);
    }
}
▶ Experimente
TEXT 📖 Somente leitura
{
  "name": "Zhang San",
  "age": 28
}

6. Serialização de coleções e dicionários

JsonSerializer pode serializar diretamente tipos de coleção, como listas e dicionários.

▶ Exemplo

CSHARP
using System;
using System.Collections.Generic;
using System.Text.Json;

public class Student
{
    public string Name { get; set; }
    public int Score { get; set; }
}

class Program
{
    static void Main()
    {
        var students = new List<Student>
        {
            new Student { Name = "Zhang San", Score = 90 },
            new Student { Name = "Li Si", Score = 85 },
            new Student { Name = "Wang Wu", Score = 92 }
        };

        var options = new JsonSerializerOptions { WriteIndented = true };
        string json = JsonSerializer.Serialize(students, options);
        Console.WriteLine(json);

        var scores = new Dictionary`<string, int>`
        {
            ["Chinese"] = 90,
            ["Math"] = 95,
            ["English"] = 88
        };
        string dictJson = JsonSerializer.Serialize(scores, options);
        Console.WriteLine(dictJson);
    }
}
▶ Experimente
TEXT 📖 Somente leitura
[
  {
    "Name": "Zhang San",
    "Score": 90
  },
  {
    "Name": "Li Si",
    "Score": 85
  },
  {
    "Name": "Wang Wu",
    "Score": 92
  }
]
{
  "Chinese": 90,
  "Math": 95,
  "English": 88
}

7. JSON dinâmico: JsonDocument e JsonElement

Quando a estrutura JSON é incerta, você pode usar JsonDocument e JsonElement para realizar uma análise dinâmica sem classes predefinidas.

▶ Exemplo

CSHARP
using System;
using System.Text.Json;

class Program
{
    static void Main()
    {
        string json = @"{""name"":""Zhang San"",""age"":28,""hobbies"":[""programming"",""reading""]}";

        using JsonDocument doc = JsonDocument.Parse(json);
        JsonElement root = doc.RootElement;

        string name = root.GetProperty("name").GetString();
        int age = root.GetProperty("age").GetInt32();
        JsonElement hobbies = root.GetProperty("hobbies");

        Console.WriteLine($"Name: {name}, Age: {age}");
        foreach (JsonElement hobby in hobbies.EnumerateArray())
        {
            Console.WriteLine($"Hobby: {hobby.GetString()}");
        }
    }
}
▶ Experimente
TEXT 📖 Somente leitura
Name: Zhang San, Age: 28
Hobby: programming
Hobby: reading

8. Serialização personalizada: JsonConverter

Herdar de JsonConverter<T> e sobrescrever os métodos Read e Write para implementar uma lógica personalizada de serialização/desserialização.

▶ Exemplo

CSHARP
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

public class DateOnlyConverter : JsonConverter`<DateTime>`
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.ParseExact(reader.GetString(), "yyyy-MM-dd", null);
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
    }
}

public class Event
{
    public string Title { get; set; }

    [JsonConverter(typeof(DateOnlyConverter))]
    public DateTime Date { get; set; }
}

class Program
{
    static void Main()
    {
        var evt = new Event
        {
            Title = "Product Launch",
            Date = new DateTime(2025, 6, 15)
        };

        string json = JsonSerializer.Serialize(evt);
        Console.WriteLine(json);

        Event deserialized = JsonSerializer.Deserialize<Event>(json);
        Console.WriteLine($"Title: {deserialized.Title}, Date: {deserialized.Date:yyyy-MM-dd}");
    }
}
▶ Experimente
TEXT 📖 Somente leitura
{"Title":"Product Launch","Date":"2025-06-15"}
Title: Product Launch, Date: 2025-06-15

9. Combinando JSON com LINQ

Após deserializar o JSON em uma coleção, você pode usar o LINQ para realizar consultas, filtragens e agregações.

▶ Exemplo

CSHARP 📖 Somente leitura
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;

public class Student
{
    public string Name { get; set; }
    public int Score { get; set; }
    public string City { get; set; }
}

class Program
{
    static void Main()
    {
        string json = @"[
            {""Name"":""Zhang San"",""Score"":90,""City"":""Beijing""},
            {""Name"":""Li Si"",""Score"":85,""City"":""Shanghai""},
            {""Name"":""Wang Wu"",""Score"":92,""City"":""Beijing""},
            {""Name"":""Zhao Liu"",""Score"":78,""City"":""Shanghai""},
            {""Name"":""Qian Qi"",""Score"":95,""City"":""Beijing""}
        ]";

        List<Student> students = JsonSerializer.Deserialize<List<Student>>(json);

        var beijingTop = students
            .Where(s => s.City == "Beijing")
            .OrderByDescending(s => s.Score)
            .ToList();

        Console.WriteLine("Beijing students (sorted by score, descending):");
        foreach (var s in beijingTop)
        {
            Console.WriteLine($"  {s.Name}: {s.Score}");
        }

        var cityAvg = students
            .GroupBy(s => s.City)
            .Select(g => new { City = g.Key, Avg = g.Average(s => s.Score) });

        Console.WriteLine("\nAverage score by city:");
        foreach (var item in cityAvg)
        {
            Console.WriteLine($"  {item.City}: {item.Avg:F1}");
        }
    }
}
41 linhas de lógica (limite de 40, somente leitura)
TEXT 📖 Somente leitura
Beijing students (sorted by score, descending):
  Qian Qi: 95
  Wang Wu: 92
  Zhang San: 90

Average score by city:
  Beijing: 92.3
  Shanghai: 81.5

10. Introdução à leitura e gravação de arquivos CSV

CSV (Comma-Separated Values) é um formato de texto que separa os campos por vírgulas, comumente usado para exportação e troca de dados. A biblioteca padrão do C# não oferece suporte integrado a CSV; você pode analisá-lo manualmente ou usar uma biblioteca de terceiros, como CsvHelper.

▶ Exemplo

CSHARP
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

class Program
{
    static void Main()
    {
        var records = new List<string[]>
        {
            new[] { "Name", "Age", "City" },
            new[] { "Zhang San", "28", "Beijing" },
            new[] { "Li Si", "25", "Shanghai" }
        };

        string csvPath = "data.csv";
        File.WriteAllLines(csvPath, records.Select(r => string.Join(",", r)));

        string[] lines = File.ReadAllLines(csvPath);
        foreach (string line in lines)
        {
            string[] fields = line.Split(',');
            Console.WriteLine($"{fields[0],-10} {fields[1],-4} {fields[2]}");
        }
    }
}
▶ Experimente
TEXT 📖 Somente leitura
Name       Age   City
Zhang San  28    Beijing
Li Si      25    Shanghai

💡 Dica: Para ambientes de produção, recomenda-se usar o CsvHelper (pacote NuGet), que lida corretamente com campos que contêm vírgulas, aspas e quebras de linha, evitando erros comuns da análise manual.

❓ Perguntas Frequentes

P: Qual é a diferença entre System.Text.Json e Newtonsoft.Json? R: System.Text.Json é uma biblioteca de alto desempenho integrada ao .NET, enquanto Newtonsoft.Json é uma biblioteca de terceiros com recursos mais abrangentes. Em novos projetos, deve-se dar preferência à biblioteca integrada.

P: E se os nomes das propriedades apresentarem diferenças de maiúsculas e minúsculas durante a desserialização? R: Defina PropertyNameCaseInsensitive = true em JsonSerializerOptions para ignorar as diferenças de maiúsculas e minúsculas.

P: Como faço para excluir uma propriedade da serialização? R: Adicione o atributo [JsonIgnore] a essa propriedade para ignorá-la.

P: Como faço para controlar o formato de data no JSON? R: Crie um JsonConverter<DateTime> personalizado e sobrescreva o método Write para especificar a string de formato de data desejada.

📖 Resumo

📝 Exercícios

  1. Defina uma classe Book (Título, Autor, Preço, EstáPublicado), serialize-a em uma string JSON com indentação e exiba-a; em seguida, deserialize-a de volta para um objeto
  2. Crie um List<Book> com pelo menos 3 livros, converta-o para JSON e, em seguida, use o LINQ para filtrar os livros cujo preço seja superior a 50
  3. Escreva um JsonConverter personalizado que serialize DateTime no formato "yyyy/MM/dd" e verifique se a desserialização o restaura corretamente
  4. Serializar um Dictionary<string, string> para JSON e salvá-lo em um arquivo; em seguida, ler o arquivo e deserializá-lo novamente
  5. Escreva uma lógica manual de leitura/gravação de CSV que lide com campos contendo vírgulas (coloque-os entre aspas duplas)
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%