CodeGym /Cursos /C# SELF /Uso de Newtonsoft.Json

Uso de Newtonsoft.Json

C# SELF
Nivel 44, Lección 4
Disponible

1. Introducción

Newtonsoft.Json es una especie de dinosaurio en el buen sentido. Fue el estándar de facto para trabajar con JSON en el ecosistema .NET durante muchos años, incluso antes de que System.Text.Json apareciera. Millones de proyectos, miles de librerías y frameworks (incluso muchas partes de ASP.NET Core hasta hace poco) usaban Json.NET.

Sus ventajas son:

  • Rico en funcionalidades y muy flexible: Json.NET ofrece un montón de opciones, atributos y posibilidades para personalizar el proceso de serialización y deserialización. Puede hacer cosas que System.Text.Json o las hace con dificultad o directamente no las soporta.
  • Tolerante con JSON "no perfecto": los datos provenientes de sistemas externos no siempre son perfectos — Json.NET suele ser más permisivo y permite deserializar sin tanto dolor.
  • Retrocompatible: si un proyecto o librería depende de Json.NET, saber trabajar con él sigue siendo necesario.

Claro, System.Text.Json es más rápido y fue pensado con requisitos modernos. Pero Newtonsoft.Json sigue siendo una herramienta potente, especialmente si necesitas lógica específica o máxima flexibilidad.

¿Cómo instalar Newtonsoft.Json?

Como es una librería externa, añade el paquete vía NuGet:

  1. Abre el proyecto.
  2. Haz clic derecho sobre el proyecto en Solution Explorer.
  3. Selecciona "Manage NuGet Packages...".
  4. En la búsqueda escribe Newtonsoft.Json.
  5. Selecciona el paquete y pulsa "Install".

Después de la instalación aparecerá una nueva dependencia — ¡ya puedes usar Json.NET!

Comparación de capacidades entre Newtonsoft.Json y System.Text.Json

Funcionalidad System.Text.Json Newtonsoft.Json
Serialización/deserialización simple Sí Sí
Soporte de atributos para propiedades Parcial Completo
Convertidores personalizados Sí Sí
Trabajo con campos privados No Sí
Trabajo con estructuras dinámicas Limitado Sí
LINQ to JSON (JObject/JArray) No Sí
Reference Loop Handling Sí Sí
Soporte para DataTable, DataSet y tipos complejos No Sí
Rendimiento Mejor Bueno

2. Ejemplo de serialización y deserialización de un objeto simple

Tomemos una estructura de juego común, que iremos expandiendo a lo largo de las lecciones:

public class Player
{
    public string Name { get; set; }
    public int Health { get; set; }
    public bool IsAlive { get; set; }
    public List<string> Inventory { get; set; }
    public Position Position { get; set; }
}

public class Position
{
    public int X { get; set; }
    public int Y { get; set; }
}

Ahora guardemos el objeto Player en JSON y lo recuperemos:

using Newtonsoft.Json;

Player player1 = new Player
{
    Name = "Aragorn",
    Health = 100,
    IsAlive = true,
    Inventory = new List<string> { "sword", "bow", "healing potion" },
    Position = new Position { X = 10, Y = 25 }
};

// Serialización a cadena JSON
string json = JsonConvert.SerializeObject(player1, Formatting.Indented);
Console.WriteLine(json);

// Deserialización de nuevo al objeto Player
Player player2 = JsonConvert.DeserializeObject<Player>(json);
Console.WriteLine($"Nombre: {player2.Name}, salud: {player2.Health}");

¿Todo? Sí, casi, pero esto es solo la punta del iceberg. Vamos a ver por qué Newtonsoft.Json es más interesante y flexible que otras librerías.

3. Formateo, ajustes y parámetros avanzados

Cuando serializas un objeto, puedes obtener tanto una cadena compacta como un JSON bonito y legible. El comportamiento se controla con parámetros y ajustes.

Ejemplo: Diferentes variantes de formateo

// JSON bonito y legible
string prettyJson = JsonConvert.SerializeObject(player1, Formatting.Indented);

// JSON compacto "minificado"
string compactJson = JsonConvert.SerializeObject(player1, Formatting.None);

Ajustes de serialización

Si necesitas, pasa JsonSerializerSettings para un control fino:

var settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore, // Omitir campos con valor null
    DefaultValueHandling = DefaultValueHandling.Ignore, // Omitir campos con valor por defecto
    Formatting = Formatting.Indented
};
string customJson = JsonConvert.SerializeObject(player1, settings);

Obtienes control total sobre el formato de salida: quieres omitir campos vacíos — adelante. Necesitas serializar incluso propiedades privadas — configura el contrato.

4. Control de campos y propiedades con atributos

Newtonsoft.Json soporta un sistema potente de atributos que configuran la serialización directamente en la clase.

JsonProperty — Renombrar propiedades

Si el protocolo JSON requiere otro nombre de campo:

public class Player
{
    [JsonProperty("player_name")]
    public string Name { get; set; }
    // ...
}

JSON resultante:

{ "player_name": "Aragorn", ... }

JsonIgnore — Ignorar una propiedad

public class Player
{
    [JsonIgnore]
    public int Health { get; set; }
}

Ahora el campo Health desaparecerá durante la serialización.

JsonConverter — Conversiones personalizadas

Permite indicar qué converter usar para procesar un campo concreto.

public class Player
{
    [JsonConverter(typeof(InventoryToStringConverter))]
    public List<string> Inventory { get; set; }
}

(Más sobre converters — abajo.)

5. Trabajo con objetos anidados y colecciones

Json.NET maneja muy bien objetos anidados, arrays, colecciones y diccionarios.

Ejemplo: Diccionarios

public class GameStats
{
    public Dictionary<string, int> Scores { get; set; }
}

GameStats stats = new GameStats
{
    Scores = new Dictionary<string, int>
    {
        ["Alice"] = 1023,
        ["Bob"] = 999
    }
};

string statsJson = JsonConvert.SerializeObject(stats, Formatting.Indented);
Console.WriteLine(statsJson);

El JSON resultante será así:

{
  "Scores": {
    "Alice": 1023,
    "Bob": 999
  }
}

6. Estructuras complejas: referencias cíclicas, Self-Referencing Objects

A veces los objetos se referencian entre sí. Newtonsoft.Json soporta la serialización de esas estructuras mediante ajustes especiales.

Ejemplo: Resolver referencias cíclicas

public class Person
{
    public string Name { get; set; }
    public Person Parent { get; set; }
    public List<Person> Children { get; set; }
}

// Configuramos la serialización para ciclos
var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore // o .Serialize
};

Person p1 = new Person { Name = "Papá" };
Person p2 = new Person { Name = "Hijo", Parent = p1 };
p1.Children = new List<Person> { p2 };

string json = JsonConvert.SerializeObject(p1, settings);
Console.WriteLine(json);

Por defecto, si dejas ReferenceLoopHandling = Error, obtendrás una excepción. Esto protege de una serialización infinita accidental.

7. Trabajo con estructuras dinámicas: JObject, JArray

Cuando la estructura JSON no es conocida de antemano o cambia en tiempo de ejecución, usa objetos dinámicos sin tipado estricto en C#.

Tipos principales:

  • JObject — representación de un objeto JSON.
  • JArray — representación de un array.
using Newtonsoft.Json.Linq;

// Convertir una cadena a JObject
string json = @"{ 'name': 'Aragorn', 'health': 100 }";
JObject obj = JObject.Parse(json);

Console.WriteLine((string)obj["name"]); // Aragorn
Console.WriteLine((int)obj["health"]);  // 100

// Añadir propiedades dinámicamente
obj["class"] = "Ranger";
Console.WriteLine(obj.ToString());

Iterar sobre un array

string jsonArr = @"['apple', 'banana', 'cherry']";
JArray array = JArray.Parse(jsonArr);

foreach (JToken item in array)
{
    Console.WriteLine(item);
}

8. Soporte de versionado y campos obligatorios

El formato JSON puede cambiar, pueden faltar campos. Usa atributos y ajustes:

  • [JsonProperty(Required = Required.Always)] — exigir la presencia del campo (si no, excepción).
  • [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] — rellenar con el valor por defecto si falta el campo.
public class Player
{
    [JsonProperty(Required = Required.Always)]
    public string Name { get; set; }

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
    [DefaultValue(50)]
    public int Health { get; set; }
}

9. Conversión de fechas y formatos de tiempo

Trabajar con fechas suele requerir un formato explícito.

var dateSettings = new JsonSerializerSettings
{
    DateFormatString = "yyyy-MM-dd"
};
string json = JsonConvert.SerializeObject(DateTime.Now, dateSettings);
Console.WriteLine(json); // "2024-06-15"

Y de vuelta al deserializar:

string dateJson = "\"2024-06-15\""; // ¡Fíjate: eso es una cadena entre comillas!
DateTime dt = JsonConvert.DeserializeObject<DateTime>(dateJson);
Console.WriteLine(dt);
2
Tarea
C# SELF, nivel 44, lección 4
Bloqueada
Uso de los atributos JsonProperty y JsonIgnore
Uso de los atributos JsonProperty y JsonIgnore
1
Cuestionario/control
Clases estándar de serialización, nivel 44, lección 4
No disponible
Clases estándar de serialización
Clases y librerías para serialización
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION