Работа с JSON в C#: парсинг и сериализация на практике

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение

JSON (JavaScript Object Notation) — это легковесный формат обмена данными, который стал стандартом де-факто для взаимодействия между сервером и клиентом, а также для хранения конфигураций. В экосистеме C# (.NET) работа с JSON реализована на высшем уровне: разработчику доступны как встроенные библиотеки, так и мощные сторонние решения. В этой статье мы на практических примерах разберем, как выполнять парсинг, сериализацию и десериализацию JSON в C#, используя современные подходы.

Мы рассмотрим два основных инструмента: System.Text.Json (встроенная библиотека с .NET Core 3.0+) и Newtonsoft.Json (популярная сторонняя библиотека). Вы узнаете, как преобразовывать объекты C# в JSON и обратно, как работать с вложенными структурами и как обрабатывать ошибки.

Основы сериализации и десериализации в C#

Прежде чем углубляться в код, давайте определимся с терминами. Сериализация — это процесс преобразования объекта C# (например, экземпляра класса) в строку JSON. Десериализация — обратный процесс: из JSON-строки мы восстанавливаем объект C#. В C# для этого используются атрибуты и специальные классы-сериализаторы.

1. Работа с System.Text.Json (встроенная библиотека)

Начиная с .NET Core 3.0, Microsoft представила собственную библиотеку для работы с JSON — System.Text.Json. Она быстрее Newtonsoft.Json и не требует установки дополнительных пакетов.

Рассмотрим простой класс Person:

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

Сериализация в JSON:

using System.Text.Json;

var person = new Person
{
    Name = "Алексей",
    Age = 30,
    Email = "alex@example.com"
};

string json = JsonSerializer.Serialize(person);
Console.WriteLine(json);
// Вывод: {"Name":"Алексей","Age":30,"Email":"alex@example.com"}

Десериализация из JSON:

string jsonString = @"{""Name"":""Мария"",""Age"":25,""Email"":""maria@example.com""}";
Person? person = JsonSerializer.Deserialize<Person>(jsonString);
Console.WriteLine(person?.Name); // Мария

Обратите внимание на оператор ? (nullable) — десериализация может вернуть null при ошибке.

2. Работа с Newtonsoft.Json (Json.NET)

Несмотря на появление System.Text.Json, Newtonsoft.Json остается популярным выбором благодаря своей гибкости и обширным возможностям настройки. Для его использования установите NuGet-пакет Newtonsoft.Json.

Пример с тем же классом Person:

using Newtonsoft.Json;

// Сериализация
var person = new Person { Name = "Иван", Age = 35, Email = "ivan@example.com" };
string json = JsonConvert.SerializeObject(person);
Console.WriteLine(json);

// Десериализация
string jsonInput = @"{'Name':'Ольга','Age':28,'Email':'olga@example.com'}";
Person? personDeserialized = JsonConvert.DeserializeObject<Person>(jsonInput);
Console.WriteLine(personDeserialized?.Name); // Ольга

Newtonsoft.Json по умолчанию поддерживает как двойные кавычки, так и одинарные, что делает его более толерантным к "грязному" JSON.

Продвинутые сценарии: работа с вложенными объектами и коллекциями

В реальных проектах JSON редко бывает плоским. Рассмотрим пример с вложенными данными.

Допустим, у нас есть класс Company, содержащий список сотрудников:

public class Employee
{
    public string Name { get; set; }
    public string Position { get; set; }
}

public class Company
{
    public string CompanyName { get; set; }
    public List<Employee> Employees { get; set; }
}

Сериализация (System.Text.Json):

var company = new Company
{
    CompanyName = "TechCorp",
    Employees = new List<Employee>
    {
        new Employee { Name = "Дмитрий", Position = "Разработчик" },
        new Employee { Name = "Елена", Position = "Тестировщик" }
    }
};

string json = JsonSerializer.Serialize(company, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(json);

Результат будет отформатирован с отступами:

{
  "CompanyName": "TechCorp",
  "Employees": [
    {
      "Name": "Дмитрий",
      "Position": "Разработчик"
    },
    {
      "Name": "Елена",
      "Position": "Тестировщик"
    }
  ]
}

Десериализация вложенного JSON:

string complexJson = @"{""CompanyName"":""SoftLab"",""Employees"":[{""Name"":""Анна"",""Position"":""Аналитик""}]}";
Company? companyDeserialized = JsonSerializer.Deserialize<Company>(complexJson);
Console.WriteLine(companyDeserialized?.Employees[0].Name); // Анна

Настройка сериализации: атрибуты и кастомные конвертеры

Часто требуется изменить поведение сериализации по умолчанию. Например, переименовать поля в JSON или игнорировать null-значения.

Использование атрибутов в System.Text.Json

using System.Text.Json.Serialization;

public class Product
{
    [JsonPropertyName("product_id")]
    public int Id { get; set; }

    [JsonIgnore]
    public string InternalCode { get; set; }

    public string Name { get; set; }
}

// Сериализация
var product = new Product { Id = 1, InternalCode = "SECRET", Name = "Ноутбук" };
string json = JsonSerializer.Serialize(product, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull });
Console.WriteLine(json);
// Вывод: {"product_id":1,"Name":"Ноутбук"}

Атрибут [JsonPropertyName] меняет имя ключа, [JsonIgnore] исключает свойство из JSON, а опция DefaultIgnoreCondition убирает null-поля.

Кастомный конвертер для сложных типов

Если нужно сериализовать, например, DateTime в нестандартном формате, создайте свой конвертер:

public class CustomDateTimeConverter : JsonConverter<DateTime>                

Блоги

Рекомендаций по книгам