Привет, Хабр!
Сегодня поговорим о том, как сериализовать данные в C# с помощью библиотеки System.Text.Json. Если вы раньше использовали Newtonsoft.Json для преобразования объектов в JSON и обратно, то пришло время посмотреть, как этот процесс можно ускорить и упростить, применяя встроенные инструменты .NET.
System.Text.Json
Сначала взглянем на самый простой сценарий — сериализация объектов в JSON и обратное преобразование. System.Text.Json имеет много методов для работы с JSON, и основные из них — это JsonSerializer.Serialize()
и JsonSerializer.Deserialize()
:
using System.Text.Json;
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int EmployeeId { get; set; }
}
var employee = new Employee
{
FirstName = "Vasya",
LastName = "Pupkin",
EmployeeId = 1234
};
// сериализация объекта Employee в строку JSON
string json = JsonSerializer.Serialize(employee);
Console.WriteLine(json); // {"FirstName":"Vasya","LastName":"Pupkin","EmployeeId":1234}
// десериализация JSON обратно в объект Employee
Employee deserializedEmployee = JsonSerializer.Deserialize<Employee>(json);
Console.WriteLine(deserializedEmployee.FirstName); // Vasya
Всё просто: создаешь объект, сериализуешь его в строку JSON и обратно.
Вложенные объекты
public class Address
{
public string City { get; set; }
public string Country { get; set; }
}
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int EmployeeId { get; set; }
public Address EmployeeAddress { get; set; }
}
var employee = new Employee
{
FirstName = "Nastya",
LastName = "Orlova",
EmployeeId = 1234,
EmployeeAddress = new Address { City = "New York", Country = "USA" }
};
string json = JsonSerializer.Serialize(employee);
Console.WriteLine(json);
// {"FirstName":"Nastya","LastName":"Orlova","EmployeeId":1234,"EmployeeAddress":{"City":"New York","Country":"USA"}}
Employee deserializedEmployee = JsonSerializer.Deserialize<Employee>(json);
Console.WriteLine(deserializedEmployee.EmployeeAddress.City); // New York
JSON работает с вложенными объектами так же, как и с простыми, сериализация происходит рекурсивно.
System.Text.Json позволяет настроить процесс сериализации через JsonSerializerOptions
. Например, можно управлять форматированием JSON или игнорировать значения null
.
Пример:
var options = new JsonSerializerOptions
{
WriteIndented = true, // Включаем красивое форматирование
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull // Игнорируем null значения
};
var employee = new Employee
{
FirstName = "Sonya",
LastName = null, // Это поле будет проигнорировано
EmployeeId = 1234
};
string json = JsonSerializer.Serialize(employee, options);
Console.WriteLine(json);
// {
// "FirstName": "Sonya",
// "EmployeeId": 1234
// }
Опция WriteIndented
хороша, когда нужно сделать JSON более читаемым, например, для логирования. А вот DefaultIgnoreCondition
позволяет игнорировать пустые или null
поля — удобно для экономии места в передаваемых данных.
Еще можно обрабатывать данные, которые не поддерживаются по умолчанию. Например, сложные объекты или специфические форматы. Для этого нужно создать кастомный конвертер с помощью JsonConverter
.
Пример кастомного конвертера для DateTime:
public class CustomDateTimeConverter : JsonConverter<DateTime>
{
private const string Format = "yyyy-MM-dd";
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string dateString = reader.GetString();
return DateTime.ParseExact(dateString, Format, null);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(Format));
}
}
var options = new JsonSerializerOptions
{
Converters = { new CustomDateTimeConverter() },
WriteIndented = true
};
DateTime now = DateTime.Now;
string json = JsonSerializer.Serialize(now, options);
Console.WriteLine(json); // "2024-09-07"
Здесь переопределяем методы Read
и Write
, чтобы работать с датами в специфичном формате.
Асинхронная сериализация
Когда работаем с потоками или большими объемами данных, асинхронные операции помогают избежать блокировок:
using (FileStream fs = new FileStream("data.json", FileMode.Create))
{
var employee = new Employee { FirstName = "Alex", LastName = "Champion", EmployeeId = 1234 };
await JsonSerializer.SerializeAsync(fs, employee);
}
Сериализация в байты
Если нужно максимизировать производительность, можно сериализовать объект в массив байт, что ускоряет передачу данных:
byte[] jsonBytes = JsonSerializer.SerializeToUtf8Bytes(employee);
Это на 5-10% быстрее, чем обычная сериализация в строку.
JsonDocument
Если нужно читать или манипулировать большими JSON-структурами, которые сложно или нежелательно сериализовать в объект, то в помощь идет JsonDocument
:
string jsonString = "{\"FirstName\":\"Artem\",\"LastName\":\"Artemovich\",\"EmployeeId\":1234}";
using (JsonDocument doc = JsonDocument.Parse(jsonString))
{
JsonElement root = doc.RootElement;
string firstName = root.GetProperty("FirstName").GetString();
Console.WriteLine(firstName);
}
Этот подход позволяет работать с JSON на уровне элементов, не создавая для этого целые объекты.
Итог: System.Text.Json — это мощный инструмент для работы с JSON в C#. Он позволяет легко сериализовать и десериализовать объекты, и к тому же настраивать процесс, используя различные опции и кастомные конвертеры.
Как эффективно использовать асинхронность в C# для улучшения производительности приложений? Обсудим это на открытом уроке 12 сентября. Какие темы успеем затронуть:
Основы асинхронности в C#: рассмотрим ключевые концепции и принципы асинхронного программирования.
Async и Await: подробно разберем ключевые слова async и await, их использование и влияние на код.
Лучшие практики: Советы и рекомендации по оптимизации и улучшению асинхронного кода.
Записаться на урок можно на странице курса "C# Developer. Professional".