JavaRush /Курсы /C# SELF /Применение Newtonsoft.Json...

Применение Newtonsoft.Json

C# SELF
44 уровень , 4 лекция
Открыта

1. Введение

Newtonsoft.Json — это своего рода динозавр в хорошем смысле слова. Он был де-факто стандартом для работы с JSON в экосистеме .NET на протяжении многих лет, ещё до того, как System.Text.Json вообще появился на свет. Миллионы проектов, тысячи библиотек и фреймворков (даже многие части ASP.NET Core до недавнего времени) использовали именно Json.NET.

Его преимущества в том, что он:

  • Богат функционалом и гибок: Json.NET предлагает огромное количество настроек, атрибутов и возможностей для кастомизации процесса сериализации и десериализации. Он умеет делать вещи, которые System.Text.Json либо делает с большим трудом, либо вообще не умеет.
  • Лоялен к "неидеальному" JSON: данные из внешних систем не всегда идеальны — Json.NET чаще терпим к таким случаям и позволяет десериализовать без лишней боли.
  • Обратно совместим: если проект или библиотека завязаны на Json.NET, умение работать с ним остаётся необходимым.

Конечно, System.Text.Json быстрее и создан с учётом современных требований. Но Newtonsoft.Json до сих пор остаётся мощным инструментом, особенно если нужна специфическая логика или максимальная гибкость.

Как установить Newtonsoft.Json?

Поскольку это сторонняя библиотека, добавьте пакет через NuGet:

  1. Откройте проект.
  2. Кликните правой кнопкой по проекту в Solution Explorer.
  3. Выберите "Manage NuGet Packages...".
  4. В поиске введите Newtonsoft.Json.
  5. Выберите пакет и нажмите "Install".

После установки появится новая зависимость — можно использовать Json.NET!

Сравнение возможностей Newtonsoft.Json и System.Text.Json

Возможность System.Text.Json Newtonsoft.Json
Простая сериализация/десериализация Да Да
Поддержка атрибутов для свойств Частично Полная
Кастомные конвертеры Да Да
Работа с приватными полями Нет Да
Работа с динамическими структурами Ограниченно Да
LINQ to JSON (JObject/JArray) Нет Да
Reference Loop Handling Да Да
Поддержка DataTable, DataSet и сложных типов Нет Да
Производительность Лучше Хорошая

2. Пример сериализации и десериализации простого объекта

Возьмём общую игровую структуру, которая развивается из лекции в лекцию:

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; }
}

Теперь сохраним объект Player в JSON и восстановим его:

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 }
};

// Сериализация в JSON-строку
string json = JsonConvert.SerializeObject(player1, Formatting.Indented);
Console.WriteLine(json);

// Десериализация обратно в объект Player
Player player2 = JsonConvert.DeserializeObject<Player>(json);
Console.WriteLine($"Имя: {player2.Name}, здоровье: {player2.Health}");

Всё? Да, почти, но это только верхушка айсберга. Давайте разберём, чем Newtonsoft.Json интереснее и гибче других библиотек.

3. Форматирование, настройки и расширенные параметры

Когда сериализуете объект, можете получать как компактную строку, так и красиво отформатированный JSON. Поведение контролируется параметрами и настройками.

Пример: Разные варианты форматирования

// Красиво читабельный JSON
string prettyJson = JsonConvert.SerializeObject(player1, Formatting.Indented);

// Компактный "минифицированный" JSON
string compactJson = JsonConvert.SerializeObject(player1, Formatting.None);

Настройки сериализации

При необходимости передавайте JsonSerializerSettings для тонкой настройки:

var settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore, // Пропускать поля со значением null
    DefaultValueHandling = DefaultValueHandling.Ignore, // Пропускать поля с дефолтом
    Formatting = Formatting.Indented
};
string customJson = JsonConvert.SerializeObject(player1, settings);

Вы получаете максимальный контроль над форматом вывода: хотите пропустить пустые поля — пожалуйста. Нужно сериализовать даже приватные свойства — настройте контракт.

4. Управление полями и свойствами с помощью атрибутов

Newtonsoft.Json поддерживает мощную систему атрибутов, которые настраивают сериализацию прямо в классе.

JsonProperty — Переименование свойств

Если JSON-протокол требует иного имени поля:

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

Результирующий JSON:

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

JsonIgnore — Игнорировать свойство

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

Теперь поле Health пропадёт при сериализации.

JsonConverter — Кастомные преобразования

Позволяет указать, каким конвертером обрабатывать конкретное поле.

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

(Подробнее о конвертерах — ниже.)

5. Работа с вложенными и коллекциями объектов

Json.NET отлично справляется с вложенными объектами, массивами, коллекциями, словарями.

Пример: Словари

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);

JSON получится вот такой:

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

6. Cложные структуры: циклические ссылки, Self-Referencing Objects

Иногда объекты содержат ссылки друг на друга. Newtonsoft.Json поддерживает сериализацию таких структур через специальные настройки.

Пример: Разрешение циклических ссылок

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

// Настраиваем сериализацию для циклов
var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore // или .Serialize
};

Person p1 = new Person { Name = "Папа" };
Person p2 = new Person { Name = "Сын", Parent = p1 };
p1.Children = new List<Person> { p2 };

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

По умолчанию, если оставить ReferenceLoopHandling = Error, вы получите исключение. Это защищает от случайной бесконечной сериализации.

7. Работа с динамическими структурами: JObject, JArray

Когда структура JSON заранее неизвестна или меняется на лету, используйте динамические объекты без строгой типизации на уровне C#.

Основные типы:

  • JObject — представление JSON-объекта.
  • JArray — представление массива.
using Newtonsoft.Json.Linq;

// Преобразование строки в JObject
string json = @"{ 'name': 'Aragorn', 'health': 100 }";
JObject obj = JObject.Parse(json);

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

// Динамическое добавление свойств
obj["class"] = "Ranger";
Console.WriteLine(obj.ToString());

Итерация по массиву

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

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

8. Поддержка версионности и обязательных полей

Формат JSON может меняться, поля могут отсутствовать. Используйте атрибуты и настройки:

  • [JsonProperty(Required = Required.Always)] — требовать наличие поля (иначе исключение).
  • [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] — подставить дефолт, если поле отсутствует.
public class Player
{
    [JsonProperty(Required = Required.Always)]
    public string Name { get; set; }

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

9. Преобразование дат и форматов времени

Работа с датами часто требует явного формата.

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

И обратно при десериализации:

string dateJson = "\"2024-06-15\""; // Обратите внимание: это строка в кавычках!
DateTime dt = JsonConvert.DeserializeObject<DateTime>(dateJson);
Console.WriteLine(dt);
2
Задача
C# SELF, 44 уровень, 4 лекция
Недоступна
Использование атрибутов JsonProperty и JsonIgnore
Использование атрибутов JsonProperty и JsonIgnore
1
Опрос
Стандартные классы сериализации, 44 уровень, 4 лекция
Недоступен
Стандартные классы сериализации
Классы и библиотеки для сериализации
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ