CodeGym /Cursos /C# SELF /Mergulhando em Newtonsoft....

Mergulhando em Newtonsoft.Json

C# SELF
Nível 47 , Lição 2
Disponível

1. Introdução

Se você está começando a se familiarizar com serialização no .NET, é natural perguntar: por que outra biblioteca se já existe o embutido System.Text.Json? A resposta é simples: Newtonsoft.Json surgiu antes e, ao longo dos anos, evoluiu até ser ainda a ferramenta mais flexível para JSON no .NET.

Ela virou um padrão de fato porque suporta cenários complexos: contratos customizados, conversores poderosos, serialização de campos privados, LINQ para JSON, objetos dinâmicos (JObject), tratamento flexível de referências cíclicas e vários formatos de data/hora. Muitas bibliotecas e APIs ainda usam Json.NET "por baixo dos panos".

Importante: em certos cenários o embutido System.Text.Json ainda fica atrás das possibilidades do Newtonsoft.Json, então vale a pena aprender Json.NET.

Como adicionar Newtonsoft.Json (Json.NET)

Instale o pacote via NuGet:

dotnet add package Newtonsoft.Json

Importe o namespace:

using Newtonsoft.Json;

2. Serialização com Newtonsoft.Json

Vamos pegar a classe tradicional Person:

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

Serializando um objeto para string JSON

Person person = new Person { Name = "Ivan", Age = 30 };

// Serialização para JSON
string json = JsonConvert.SerializeObject(person);

Console.WriteLine(json);
// Saída: {"Name":"Ivan","Age":30}

Desserializando JSON de volta para um objeto

string json = "{\"Name\":\"Ivan\",\"Age\":30}";

Person person = JsonConvert.DeserializeObject<Person>(json);

Console.WriteLine($"{person.Name}, {person.Age}");
// Saída: Ivan, 30

O que acontece "por baixo do capô"?

Newtonsoft.Json itera por todas as propriedades públicas (public), serializa elas em JSON e escreve na string. Ao desserializar ele mapeia as chaves do JSON para os nomes das propriedades e popula o objeto.

3. Serialização de coleções de objetos

Serializando coleções e arrays

Com coleções tudo funciona "out of the box".

List<Person> people = new List<Person>
{
    new Person { Name = "Ivan", Age = 30 },
    new Person { Name = "Maria", Age = 25 }
};

string json = JsonConvert.SerializeObject(people);
// Saída: [{"Name":"Ivan","Age":30},{"Name":"Maria","Age":25}]

List<Person> deserialized = JsonConvert.DeserializeObject<List<Person>>(json);
// Agora você tem novamente uma lista de Person!

Particularidades na serialização e desserialização de dicionários

var dict = new Dictionary<string, int>
{
    ["apple"] = 2,
    ["banana"] = 5
};

string json = JsonConvert.SerializeObject(dict);
// Saída: {"apple":2,"banana":5}

var deserializedDict = JsonConvert.DeserializeObject<Dictionary<string,int>>(json);
// Tudo funcionando!

Se as chaves não forem strings (por exemplo, Dictionary<int,string>), o Json.NET converte as chaves para strings ao serializar, e ao desserializar tenta converter de volta. Para chaves complexas (ex.: Guid) é mais seguro usar Dictionary<string, TValue>.

4. Trabalho com objetos aninhados e hierarquias

public class Order
{
    public int Id { get; set; }
    public Person Customer { get; set; }
    public List<Product> Products { get; set; }
}
public class Product
{
    public string Title { get; set; }
    public double Price { get; set; }
}
Order order = new Order
{
    Id = 123,
    Customer = new Person { Name = "Ivan", Age = 30 },
    Products = new List<Product>
    {
        new Product { Title = "Notebook", Price = 50000.0 },
        new Product { Title = "Mouse", Price = 1500.0 }
    }
};

string json = JsonConvert.SerializeObject(order);

Console.WriteLine(json);

Resultado: objetos aninhados serão representados corretamente dentro da estrutura JSON.

5. Ajustando serialização com atributos

Ignorando uma propriedade

public class Person
{
    public string Name { get; set; }

    [JsonIgnore]
    public int Age { get; set; }
}

Agora Age não vai aparecer no JSON.

Renomeando uma propriedade

public class Person
{
    [JsonProperty("full_name")]
    public string Name { get; set; }
}

No JSON o nome vai aparecer como "full_name".

6. Configuração flexível: JsonSerializerSettings

Formatação (JSON "bonitão" com múltiplas linhas):

string json = JsonConvert.SerializeObject(
    people,
    Formatting.Indented
);

Resultado:

[
  {
    "Name": "Ivan",
    "Age": 30
  },
  {
    "Name": "Maria",
    "Age": 25
  }
]

Configurações usadas com frequência:

Propriedade Descrição
NullValueHandling
Como tratar propriedades null (omití-las ou escrever explicitamente null)
DefaultValueHandling
Omitir valores padrão ou incluí-los
ReferenceLoopHandling
O que fazer com referências cíclicas
DateFormatString
Formato de string para datas e horas

Exemplo omitindo null:

string json = JsonConvert.SerializeObject(
    person,
    new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }
);

7. Trabalhando com estruturas JSON dinâmicas: JObject, JArray e afins

Quando a estrutura do JSON é desconhecida, use os tipos de Newtonsoft.Json.Linq:

using Newtonsoft.Json.Linq;

string json = @"{
    'Name': 'Ivan',
    'Age': 30,
    'Skills': ['C#', 'SQL', 'JSON']
}";

JObject obj = JObject.Parse(json);

Console.WriteLine(obj["Name"]);     // Ivan
Console.WriteLine(obj["Skills"][0]); // C#

Criando JSON "on the fly":

var jObj = new JObject
{
    ["Status"] = "Success",
    ["Result"] = new JArray("item1", "item2", "item3")
};

Console.WriteLine(jObj.ToString(Formatting.Indented));

JObject e JArray são representações de objeto e array JSON — basicamente coleções convenientes.

8. Dicas úteis

Referências cíclicas

Newtonsoft.Json consegue tratar referências cíclicas de forma flexível:

var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};

string json = JsonConvert.SerializeObject(obj, settings);

Assim os ciclos são ignorados. Para preservar referências você pode usar ReferenceLoopHandling.Serialize junto com [JsonObject(IsReference = true)].

Serialização de objetos anônimos e dinâmicos

var anon = new { Foo = 42, Bar = "Hello" };
string json = JsonConvert.SerializeObject(anon);
// {"Foo":42,"Bar":"Hello"}

Validação e tratamento de erros

try
{
    Person p = JsonConvert.DeserializeObject<Person>(brokenJson);
}
catch (JsonSerializationException ex)
{
    Console.WriteLine("Erro ao desserializar: " + ex.Message);
}

Comparando Newtonsoft.Json vs System.Text.Json

Newtonsoft.Json (Json.NET) System.Text.Json (.NET)
Suporte .NET .NET Framework/Standard/6+ .NET Core 3.0+ / .NET 5/6/9
LINQ para JSON (JObject/JArray) Sim Não
Configuração flexível Muito ampla Limitada
Atributos ([JsonProperty], ...) Sim Sim (parcialmente, menos recursos)
Suporte a propriedades privadas Sim Não
Velocidade Mais lento em alguns cenários Mais rápido
Conversores complexos Sim Sim (menos flexível por enquanto)
Suporte a DataTable, DataSet Sim Não
Documentação e exemplos Muitos Crescendo

9. Erros de iniciantes e armadilhas comuns

Erro #1: propriedades ficam null depois da desserialização.
Frequentemente a propriedade não tem setter ou falta um construtor sem parâmetros — o serializador não tem como preencher o objeto.

Erro #2: nomes de propriedades não batem entre JSON e classe.
Se no JSON o campo for "fullName" e na classe for FullName, use [JsonProperty] ou ajuste o ContractResolver para mapear nomes.

Erro #3: serialização funciona só com propriedades públicas por padrão.
Campos/propriedades privadas não são serializados sem configuração extra. Você vai precisar de conversores ou resolvers/contratos especiais.

Erro #4: referências cíclicas levam a StackOverflowException.
Referências mútuas entre objetos podem circular a serialização sem configuração. Ajuste o tratamento de referências (por exemplo, ReferenceLoopHandling) ou mude o modelo de dados.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION