JavaRush /Курсы /C# SELF /Погружаемся в Newtonsoft.J...

Погружаемся в Newtonsoft.Json

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

1. Введение

Если вы только начали знакомиться с сериализацией в .NET, вполне естественно задаться вопросом: зачем нужна ещё одна библиотека, если уже есть встроенный System.Text.Json? Ответ прост: Newtonsoft.Json появилась раньше и за годы развилась во всё ещё самый гибкий инструмент для JSON в .NET.

Она стала де-факто стандартом, потому что поддерживает сложные сценарии: кастомные контракты, мощные конвертеры, сериализацию приватных полей, LINQ к JSON, динамические объекты (JObject), гибкую обработку циклических ссылок и множество форматов даты/времени. Много библиотек и API до сих пор используют Json.NET “под капотом”.

Важно: в ряде сценариев встроенный System.Text.Json пока уступает возможностям Newtonsoft.Json, поэтому изучение Json.NET остаётся актуальным.

Как подключить Newtonsoft.Json (Json.NET)

Установите пакет через NuGet:

dotnet add package Newtonsoft.Json

Подключите пространство имён:

using Newtonsoft.Json;

2. Сериализация через Newtonsoft.Json

Возьмём традиционный класс Person:

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

Сериализация объекта в строку JSON

Person person = new Person { Name = "Иван", Age = 30 };

// Сериализация в JSON
string json = JsonConvert.SerializeObject(person);

Console.WriteLine(json);
// Вывод: {"Name":"Иван","Age":30}

Десериализация JSON обратно в объект

string json = "{\"Name\":\"Иван\",\"Age\":30}";

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

Console.WriteLine($"{person.Name}, {person.Age}");
// Вывод: Иван, 30

Что происходит "под капотом"?

Newtonsoft.Json проходит по всем открытым свойствам (public), сериализует их в JSON и записывает в строку. При десериализации он сопоставляет ключи из JSON с именами свойств и заполняет объект.

3. Сериализация коллекций объектов

Сериализация коллекций и массивов

С коллекциями всё работает “из коробки”.

List<Person> people = new List<Person>
{
    new Person { Name = "Иван", Age = 30 },
    new Person { Name = "Мария", Age = 25 }
};

string json = JsonConvert.SerializeObject(people);
// Вывод: [{"Name":"Иван","Age":30},{"Name":"Мария","Age":25}]

List<Person> deserialized = JsonConvert.DeserializeObject<List<Person>>(json);
// Теперь у вас снова список Person!

Особенности сериализации и десериализации словарей

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

string json = JsonConvert.SerializeObject(dict);
// Вывод: {"apple":2,"banana":5}

var deserializedDict = JsonConvert.DeserializeObject<Dictionary<string,int>>(json);
// Всё работает!

Если ключи не строковые (например, Dictionary<int,string>), Json.NET преобразует ключи в строки при сериализации, а при десериализации попытается сконвертировать назад. Для сложных ключей (например, Guid) надёжнее использовать Dictionary<string, TValue>.

4. Работа с вложенными объектами и иерархиями

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 = "Иван", Age = 30 },
    Products = new List<Product>
    {
        new Product { Title = "Ноутбук", Price = 50000.0 },
        new Product { Title = "Мышка", Price = 1500.0 }
    }
};

string json = JsonConvert.SerializeObject(order);

Console.WriteLine(json);

Результат: вложенные объекты будут корректно представлены внутри JSON-структуры.

5. Настройка сериализации с помощью атрибутов

Игнорируем свойство

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

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

Теперь Age не попадёт в JSON.

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

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

В JSON имя будет как "full_name".

6. Гибкая настройка: JsonSerializerSettings

Форматирование (красивый многострочный JSON):

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

Результат:

[
  {
    "Name": "Иван",
    "Age": 30
  },
  {
    "Name": "Мария",
    "Age": 25
  }
]

Часто используемые настройки:

Свойство Описание
NullValueHandling
Как обрабатывать null-свойства (пропускать их или писать явно null)
DefaultValueHandling
Пропускать ли значения по умолчанию
ReferenceLoopHandling
Что делать с круговыми ссылками
DateFormatString
Формат строк для дат и времени

Пример с пропуском null:

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

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

Когда структура JSON заранее неизвестна, используйте типы из Newtonsoft.Json.Linq:

using Newtonsoft.Json.Linq;

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

JObject obj = JObject.Parse(json);

Console.WriteLine(obj["Name"]);     // Иван
Console.WriteLine(obj["Skills"][0]); // C#

Создание JSON “на лету”:

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

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

JObject и JArray — представления JSON-объекта и массива, по сути — удобные коллекции.

8. Полезные нюансы

Циклические ссылки

Newtonsoft.Json умеет гибко их обрабатывать:

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

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

Так циклы будут пропущены. Для сохранения ссылок можно использовать ReferenceLoopHandling.Serialize совместно с [JsonObject(IsReference = true)].

Сериализация анонимных и динамических объектов

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

Валидация и обработка ошибок

try
{
    Person p = JsonConvert.DeserializeObject<Person>(brokenJson);
}
catch (JsonSerializationException ex)
{
    Console.WriteLine("Ошибка при десериализации: " + ex.Message);
}

Сравнение Newtonsoft.Json vs System.Text.Json

Newtonsoft.Json (Json.NET) System.Text.Json (.NET)
Поддержка .NET .NET Framework/Standard/6+ .NET Core 3.0+ / .NET 5/6/9
LINQ к JSON (JObject/JArray) Да Нет
Гибкая настройка Очень большая Ограниченная
Атрибуты ([JsonProperty], ...) Да Да (частично, меньше возможностей)
Поддержка приватных свойств Да Нет
Скорость Медленнее в ряде сценариев Быстрее
Сложные конвертеры Да Да (менее гибко, пока что)
Поддержка DataTable, DataSet Да Нет
Документация и примеры Море Растёт

9. Ошибки новичков и типичные подводные камни

Ошибка №1: свойства становятся null после десериализации.
Часто у свойства нет сеттера или отсутствует конструктор без параметров — сериализатору нечем заполнить объект.

Ошибка №2: несовпадение имён свойств между JSON и классом.
Если в JSON поле "fullName", а в классе — FullName, используйте [JsonProperty] или настройте ContractResolver для сопоставления имён.

Ошибка №3: сериализация работает только с публичными свойствами по умолчанию.
Приватные поля/свойства не сериализуются без доп. настроек. Нужны конвертеры или специальные резолверы/контракты.

Ошибка №4: циклические ссылки приводят к StackOverflowException.
Взаимные ссылки объектов зацикливают сериализацию без настроек. Настраивайте обработку ссылок (например, ReferenceLoopHandling) или меняйте модель данных.

2
Задача
C# SELF, 47 уровень, 2 лекция
Недоступна
Работа с вложенными структурами
Работа с вложенными структурами
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Slevin Уровень 59
27 февраля 2026
Плохая лекция. Повтор из пустого в порожнее, при этом действительно углубленные темы обходятся десятой дорогой.