1. Введение
Раз уж мы решили «разбирать LEGO-фигурку на детали», давайте разберёмся, какие у нас есть для этого инструменты в .NET. Иными словами — какие стандартные классы помогают сериализовать и десериализовать объекты в разные форматы и что стоит за каждым из них.
Как устроено сериализационное семейство .NET
На текущий (2025) момент .NET предлагает несколько основных подходов к сериализации, каждый с собственным набором классов и инструментов. Основные и наиболее часто встречающиеся:
- JSON-сериализация — основной и самый современный вариант, используется в большинстве проектов.
- XML-сериализация — чуть более старомодный, но до сих пор активно применяемый.
- Бинарная сериализация — только для особых случаев и обычно через современные сторонние решения.
Многие примеры и большая часть кода в .NET 9 используют именно JSON, и это не мода — это индустриальный стандарт. Но .NET поддерживает и иные способы — на всякий случай.
Главные герои .NET сериализации
| Формат | Класс сериализации | Простота | Производительность | Безопасность | Актуальность |
|---|---|---|---|---|---|
| JSON | |
🔥🔥🔥 | 🔥🔥🔥 | 🔥🔥🔥 | Самая актуальная |
| XML | |
🔥🔥 | 🔥🔥 | 🔥🔥 | Используется |
| JSON | Newtonsoft.Json (Json.NET) | 🔥🔥🔥 | 🔥🔥 | 🔥🔥🔥 | Очень популярен |
Коротко о каждом
- System.Text.Json: Новый стандарт сериализации JSON в .NET, появился в .NET Core 3.0, стал основным в .NET 5+. Быстрый, лёгкий, безопасный, встроен “из коробки” в .NET 9. Документация
- XmlSerializer: Старый и проверенный вариант для сериализации в XML. Простой в использовании, но с ограничениями (например, нужен public-класс и публичные свойства). Хорош для совместимости и строгих контрактов данных. Документация
- Newtonsoft.Json: Долгое время был де-факто стандартом JSON-сериализации до появления System.Text.Json. Часто используется для сложных сценариев (динамика, приватные свойства и т.п.). Документация
Куда делся BinaryFormatter?
Если вы встретите в интернете советы использовать BinaryFormatter — скорее всего, это древний туториал. Не используйте BinaryFormatter: он удалён из .NET 9 по соображениям безопасности. Современную бинарную сериализацию обеспечивают сторонние решения — например, Protobuf или MessagePack.
2. Простые примеры
Давайте попробуем применить на практике сериализацию и десериализацию на примере нашего уже знакомого класса Player из игровой вселенной.
Подготовим класс для сериализации
// Player.cs
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; }
}
a) Сериализация и десериализация в JSON с помощью System.Text.Json
using System.Text.Json;
Player aragorn = new Player
{
Name = "Aragorn",
Health = 100,
IsAlive = true,
Inventory = new List<string> { "sword", "bow", "healing potion" },
Position = new Position { X = 10, Y = 25 }
};
// Сериализация объекта Player в строку JSON
string json = JsonSerializer.Serialize(aragorn);
// Выведем JSON на экран
Console.WriteLine(json);
// Десериализация строки JSON обратно в объект Player
Player? aragornClone = JsonSerializer.Deserialize<Player>(json);
// Проверим, работает ли клон :)
Console.WriteLine(aragornClone?.Name); // Должно вывести "Aragorn"
Вот так всё просто — никаких «танцев с бубном» и магических атрибутов. А теперь — как это выглядит в XML.
b) Сериализация и десериализация в XML с помощью XmlSerializer
using System.Xml.Serialization;
// Настроим сериализатор для класса Player
XmlSerializer serializer = new XmlSerializer(typeof(Player));
// Сериализация в файл
using FileStream fs = new FileStream("aragorn.xml", FileMode.Create);
serializer.Serialize(fs, aragorn); // Сохраняем Aragorn в XML-файл
// Десериализация из файла
using FileStream fs = new FileStream("aragorn.xml", FileMode.Open);
Player aragornFromXml = (Player) serializer.Deserialize(fs)!;
Console.WriteLine(aragornFromXml.Name); // Должно вывести "Aragorn"
Обратите внимание! XmlSerializer требует, чтобы классы и их свойства были публичными и имели пустой конструктор по умолчанию (если переопределяете конструктор — сделайте public и без параметров). Иначе сериализация завершится ошибкой.
c) Сериализация и десериализация в JSON с помощью Newtonsoft.Json
using Newtonsoft.Json; // Не забудьте добавить пакет Newtonsoft.Json через NuGet!
// Сериализация
string json2 = JsonConvert.SerializeObject(aragorn);
// Десериализация
Player? aragornFromNewtonsoft = JsonConvert.DeserializeObject<Player>(json2);
Console.WriteLine(aragornFromNewtonsoft?.Name); // Опять "Aragorn"
Выглядит почти так же, но у Newtonsoft.Json множество дополнительных опций — например, можно сериализовать приватные поля, настраивать форматирование и решать нетривиальные сценарии.
4. Полезные нюансы
Стандартные сериализаторы и их возможности
| Класс | Формат | Встроен в .NET | Требует NuGet-пакет? | Годен для файлов | Годен для API | Простота |
|---|---|---|---|---|---|---|
|
JSON | Да | Нет | Да | Да | Лёгкий |
|
JSON | Нет | Да | Да | Да | Лёгкий |
|
XML | Да | Нет | Да | Часто | Лёгкий |
Как узнать, какой класс использовать?
Если вы не знаете, зачем вам XML — почти всегда берите JSON и System.Text.Json. Это быстрее, проще и соответствует современным практикам.
XML стоит выбирать, если:
- Вы интегрируетесь со старыми системами, которые требуют именно XML.
- Нужна строгая схема и валидация структуры данных.
- Структуры большие, стабильные и важна формальная совместимость (настройки, конфиги, обмен с enterprise-системами).
JSON — если:
- Создаёте современное приложение, взаимодействуете с вебом и мобильными устройствами.
- Нужны простота, читаемость и компактность.
- Не хочется тянуть лишние зависимости.
Newtonsoft.Json — если:
- Нужна сериализация приватных полей, особые кастомизации, полная гибкость.
- Или проект уже унаследовал эту библиотеку и миграция нецелесообразна прямо сейчас.
5. Типичные ошибки и подводные камни
Кодировка. Основные классы сериализации (особенно при работе с файлами) используют стандартную UTF-8. Если видите «кракозябры», проверьте, как вы читаете/пишете файлы и явную установку кодировки. Документация по настройке кодировки.
Неподдерживаемые типы. Некоторые стандартные сериализаторы (особенно XML) не умеют сериализовать, например, словари (Dictionary), приватные/protected-поля, события, делегаты и интерфейсы. Обычно поддерживаются публичные простые свойства и классы.
Версии классов. Если вы меняете структуру классов (добавили/переименовали/удалили свойства), старые сохранённые данные могут не прочитаться или десериализоваться некорректно. Планируйте версионирование форматов.
Null-значения. При десериализации, если в данных нет какого-то поля, соответствующее свойство получит значение по умолчанию (для ссылочного типа — null). Не забывайте о проверках.
Атрибуты. Для точной настройки часто используют атрибуты вроде [JsonIgnore], [XmlElement] и др. Они позволяют исключать свойства, менять имена элементов и управлять форматом — подробности в следующих лекциях.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ