JavaRush /Курси /C# SELF /Застосування Newtonsoft.Js...

Застосування 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. Складні структури: циклічні посилання, самопосилальні об’єкти

Іноді об’єкти містять посилання один на одного. 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);
1
Опитування
Стандартні класи серіалізації, рівень 44, лекція 4
Недоступний
Стандартні класи серіалізації
Класи та бібліотеки для серіалізації
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ