Сериализация и форматы данных

Поддерживаемые форматы

IgdrasilCore поддерживает несколько форматов сериализации для разных потребностей:

Для простых объектов (Утилиты)

Утилита Формат Использование Скорость Размер Читаемость
JsonUtils JSON Конфигурация, веб, обмен ⭐⭐⭐ ⭐⭐ Очень хорошая
YamlUtils YAML Человеческие конфиги ⭐⭐ ⭐⭐ Отличная
XmlUtils XML Структурированные данные ⭐⭐ Хорошая
PropertiesUtils Properties Плоские структуры (key=value) ⭐⭐⭐ ⭐⭐⭐ Хорошая

Для AssetBundle контейнеров (IAssetBundleSerializer)

Сериализатор Использование Скорость Размер Читаемость
JSON Отладка, веб-интеграция ⭐⭐⭐ ⭐⭐ Отличная
XML Структурированные данные ⭐⭐ Хорошая
YAML Конфиги ассетов ⭐⭐ ⭐⭐ Отличная
Binary Быстрая загрузка ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ Плохая
Compressed + Сжатие (Deflate/GZip/LZMA) ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ Плохая
Encrypted + AES шифрование ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ Плохая
Properties Плоские структуры ⭐⭐⭐ ⭐⭐⭐ Хорошая

JSON

Базовая сериализация

public class Player : GameObject
{
    [SerializableField]
    public string Name { get; set; }
    
    [SerializableField]
    public int Level { get; set; }
    
    [SerializableField]
    public float Experience { get; set; }
}

var player = new Player 
{ 
    Name = "Hero", 
    Level = 5, 
    Experience = 1234.5f 
};

// В JSON
string json = JsonUtils.Serialize(player);
Console.WriteLine(json);
// {
//   "GUID": "...",
//   "Name": "Hero",
//   "Level": 5,
//   "Experience": 1234.5
// }

// Из JSON
Player loaded = JsonUtils.Deserialize<Player>(json);

Работа с файлами

// JSON в строку / из строки
string json = JsonUtils.Serialize(player);
Player loaded = JsonUtils.Deserialize<Player>(json);

// JSON в байты / из байтов (UTF-8)
byte[] jsonBytes = JsonUtils.SerializeToBytes(player);
Player loadedFromBytes = JsonUtils.Deserialize<Player>(Encoding.UTF8.GetString(jsonBytes));

// Для сохранения на диск используйте File API:
string json = JsonUtils.Serialize(player, prettyPrint: true);
await File.WriteAllTextAsync("player.json", json);
Player loaded = JsonUtils.Deserialize<Player>(await File.ReadAllTextAsync("player.json"));

Сложные типы

public class Inventory : GameObject
{
    [SerializableField]
    public List<Item> Items { get; set; } = new();
    
    [SerializableField]
    public Dictionary<string, int> Resources { get; set; } = new();
}

var inventory = new Inventory();
inventory.Items.Add(new Item { ItemName = "Sword", Quantity = 1 });
inventory.Resources["Gold"] = 500;

string json = JsonUtils.Serialize(inventory);

XML

Идеально для структурированных данных с иерархией.

Сериализация и десериализация

public class GameData : GameObject
{
    [SerializableField]
    public string Title { get; set; }
    
    [SerializableField]
    public List<Player> Players { get; set; } = new();
    
    [SerializableField]
    public Dictionary<string, object> Metadata { get; set; } = new();
}

var data = new GameData
{
    Title = "Game Session",
    Players = new() { new Player { Name = "Alice" } },
    Metadata = new() { { "version", "1.0" } }
};

// В XML
string xml = XmlUtils.Serialize(data);
Console.WriteLine(xml);

// Из XML
GameData loaded = XmlUtils.Deserialize<GameData>(xml);

// С файлом - используйте File API:
string xml = XmlUtils.Serialize(data);
await File.WriteAllTextAsync("data.xml", xml);
GameData loadedData = XmlUtils.Deserialize<GameData>(await File.ReadAllTextAsync("data.xml"));

YAML

Идеально для конфигурационных файлов благодаря отличной читаемости.

Сериализация и десериализация

public class GameConfig : GameObject
{
    [SerializableField]
    public string GameTitle { get; set; }
    
    [SerializableField]
    public int MaxPlayers { get; set; }
    
    [SerializableField]
    public Dictionary<string, string> GraphicsSettings { get; set; } = new();
}

var config = new GameConfig
{
    GameTitle = "My Game",
    MaxPlayers = 4,
    GraphicsSettings = new()
    {
        { "Resolution", "1920x1080" },
        { "Quality", "Ultra" },
        { "VSync", "true" }
    }
};

// В YAML (очень читаемо)
string yaml = YamlUtils.Serialize(config);
Console.WriteLine(yaml);

// Из YAML
GameConfig loaded = YamlUtils.Deserialize<GameConfig>(yaml);

// С файлом - используйте File API:
string yaml = YamlUtils.Serialize(config);
await File.WriteAllTextAsync("game.yml", yaml);
GameConfig loadedConfig = YamlUtils.Deserialize<GameConfig>(await File.ReadAllTextAsync("game.yml"));

Properties (key=value)

Простой формат для плоских структур данных.

Сериализация и десериализация

public class AppSettings : GameObject
{
    [SerializableField]
    public string AppName { get; set; }
    
    [SerializableField]
    public string Version { get; set; }
    
    [SerializableField]
    public bool EnableDebug { get; set; }
    
    [SerializableField]
    public int MaxConnections { get; set; }
}

var settings = new AppSettings
{
    AppName = "MyApp",
    Version = "2.0",
    EnableDebug = true,
    MaxConnections = 100
};

// В Properties формат
string properties = PropertiesUtils.Serialize(settings);
Console.WriteLine(properties);
// AppName=MyApp
// Version=2.0
// EnableDebug=True
// MaxConnections=100

// Из Properties
AppSettings loaded = PropertiesUtils.Deserialize<AppSettings>(properties);

// С файлом - используйте File API:
string properties = PropertiesUtils.Serialize(settings);
await File.WriteAllTextAsync("app.properties", properties);
AppSettings loadedSettings = PropertiesUtils.Deserialize<AppSettings>(await File.ReadAllTextAsync("app.properties"));

Бинарная сериализация

Для максимальной производительности и минимального размера используйте BinaryReaderWithEndians и BinaryWriterWithEndians.

BinaryReaderWithEndians / BinaryWriterWithEndians

Классы поддерживают работу с big-endian и little-endian форматами:

var data = new MemoryStream();
var writer = new BinaryWriterWithEndians(data);

// Записать с контролем порядка байт
writer.WriteBE(12345);           // Big-endian int32
writer.WriteInt32(67890);        // Little-endian int32 (стандартный)
writer.WriteBE((short)100);      // Big-endian int16

// Читать
data.Seek(0, SeekOrigin.Begin);
var reader = new BinaryReaderWithEndians(data);

int beBigValue = reader.ReadInt32BE();   // Прочитать как big-endian
int leValue = reader.ReadInt32();        // Прочитать как little-endian
short beShort = reader.ReadInt16BE();    // Прочитать как big-endian

Пользовательская бинарная сериализация

Используйте интерфейс IBinarySerializable для пользовательской сериализации:

public class BinarySerializablePlayer : GameObject, IBinarySerializable
{
    public string Name { get; set; }
    public int Level { get; set; }
    public float Health { get; set; }
    
    public byte[] Serialize()
    {
        using var stream = new MemoryStream();
        using var writer = new BinaryWriterWithEndians(stream);
        
        writer.Write(Name);
        writer.Write(Level);
        writer.Write(Health);
        
        return stream.ToArray();
    }
    
    public void Deserialize(byte[] data)
    {
        using var stream = new MemoryStream(data);
        using var reader = new BinaryReaderWithEndians(stream);
        
        Name = reader.ReadString();
        Level = reader.ReadInt32();
        Health = reader.ReadSingle();
    }
}

// Использование
var player = new BinarySerializablePlayer 
{ 
    Name = "Hero", 
    Level = 10, 
    Health = 100 
};

byte[] serialized = player.Serialize();
await File.WriteAllBytesAsync("player.bin", serialized);

// Загрузить
byte[] data = await File.ReadAllBytesAsync("player.bin");
var loaded = new BinarySerializablePlayer();
loaded.Deserialize(data);

AssetBundle Сериализаторы

Для сохранения AssetBundle в различные форматы используйте специализированные сериализаторы, реализующие интерфейс IAssetBundleSerializer:

// JSON сериализатор (читаемый, текстовый)
var jsonSerializer = new AssetBundleJsonSerializer(prettyPrint: true);
byte[] data = jsonSerializer.Serialize(bundle);
var loaded = jsonSerializer.Deserialize(data);

// XML сериализатор (структурированный)
var xmlSerializer = new AssetBundleXmlSerializer();
byte[] data = xmlSerializer.Serialize(bundle);

// YAML сериализатор (человеко-ориентированный)
var yamlSerializer = new AssetBundleYamlSerializer();
byte[] data = yamlSerializer.Serialize(bundle);

// Бинарный сериализатор (быстрый, компактный)
var binarySerializer = new AssetBundleBinarySerializer();
byte[] data = binarySerializer.Serialize(bundle);

// С сжатием (Deflate, GZip, LZMA)
var compressedSerializer = new AssetBundleCompressedSerializer(
    CompressionLevel.Optimal,
    CompressionMethod.Deflate
);
byte[] compressed = compressedSerializer.Serialize(bundle);

// С AES шифрованием
var encryptedSerializer = new AssetBundleEncryptedSerializer(
    key: EncryptionHelper.AesGenerateKey(32),
    iv: EncryptionHelper.AesGenerateIV(),
    level: CompressionLevel.Optimal
);
byte[] encrypted = encryptedSerializer.Serialize(bundle);

// Properties формат (key=value)
var propSerializer = new AssetBundlePropertySerializer();
byte[] data = propSerializer.Serialize(bundle);

Подробнее смотрите в AssetBundle документации.


Утилиты для работы с данными

JsonUtils

// Сериализация
string json = JsonUtils.Serialize(obj);
string prettyJson = JsonUtils.Serialize(obj, indent: true);

// Десериализация
T obj = JsonUtils.Deserialize<T>(json);

// В/из байтов (UTF-8)
byte[] jsonBytes = JsonUtils.SerializeToBytes(obj);
T loaded = JsonUtils.DeserializeFromBytes<T>(jsonBytes);

// С файлами (используйте File API):
string json = JsonUtils.Serialize(obj, indent: true);
await File.WriteAllTextAsync("file.json", json);
T loaded = JsonUtils.Deserialize<T>(await File.ReadAllTextAsync("file.json"));

YamlUtils

// Сериализация
string yaml = YamlUtils.Serialize(obj);

// Десериализация
T obj = YamlUtils.Deserialize<T>(yaml);

// С файлами (используйте File API):
string yaml = YamlUtils.Serialize(obj);
await File.WriteAllTextAsync("file.yml", yaml);
T loaded = YamlUtils.Deserialize<T>(await File.ReadAllTextAsync("file.yml"));

XmlUtils

// Сериализация в XML
string xml = XmlUtils.Serialize(obj);

// Десериализация из XML
T obj = XmlUtils.Deserialize<T>(xml);

// С файлами (используйте File API):
string xml = XmlUtils.Serialize(obj);
await File.WriteAllTextAsync("file.xml", xml);
T loaded = XmlUtils.Deserialize<T>(await File.ReadAllTextAsync("file.xml"));

PropertiesUtils

// Для плоских структур (key=value формат)
string properties = PropertiesUtils.Serialize(obj);

// Десериализация
T obj = PropertiesUtils.Deserialize<T>(properties);

// С файлами (используйте File API):
string properties = PropertiesUtils.Serialize(obj);
await File.WriteAllTextAsync("file.properties", properties);
T loaded = PropertiesUtils.Deserialize<T>(await File.ReadAllTextAsync("file.properties"));

Практические примеры

Конфигурация игры из YAML

// game-config.yml
/*
game:
  title: "My RPG"
  version: "1.0"
  
difficulty:
  enemy_health: 50
  enemy_damage: 10
  
audio:
  master_volume: 0.8
  music_volume: 0.6
*/

public class GameConfiguration : GameObject
{
    [SerializableField]
    public GameInfo Game { get; set; }
    
    [SerializableField]
    public DifficultySettings Difficulty { get; set; }
    
    [SerializableField]
    public AudioSettings Audio { get; set; }
}

// Загрузить
string yamlContent = await File.ReadAllTextAsync("game-config.yml");
var config = YamlUtils.Deserialize<GameConfiguration>(yamlContent);
Console.WriteLine($"Game: {config.Game.Title} v{config.Game.Version}");

Экспорт данных в JSON для веба

var players = new List<Player>
{
    new Player { Name = "Alice", Level = 10 },
    new Player { Name = "Bob", Level = 8 }
};

// Серилизовать в JSON
string json = JsonUtils.Serialize(new { players }, indent: true);

// Отправить на сервер
using var client = new HttpClient();
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.example.com/players", content);

Сохранение с fallback к другому формату

try
{
    // Попытаться JSON
    string json = JsonUtils.Serialize(player, indent: true);
    await File.WriteAllTextAsync("player.json", json);
}
catch
{
    // Fallback на YAML
    string yaml = YamlUtils.Serialize(player);
    await File.WriteAllTextAsync("player.yml", yaml);
}

try
{
    // Попытаться JSON
    string json = await File.ReadAllTextAsync("player.json");
    return JsonUtils.Deserialize<Player>(json);
}
catch
{
    // Fallback на YAML
    string yaml = await File.ReadAllTextAsync("player.yml");
    return YamlUtils.Deserialize<Player>(yaml);
}

Перформанс и рекомендации

Сценарий Рекомендуемый формат Примечание
Сохранение данных игрока Binary или AssetBundle Binary Максимальная производительность
Конфигурация игры YAML или JSON YAML лучше для человеческого чтения
Логирование/отладка JSON Простой парсинг и читаемость
Экспорт для веба JSON Стандартный формат для API
Компактное хранилище AssetBundle Compressed С LZMA сжатием
Защита данных AssetBundle Encrypted С AES шифрованием
Структурированные данные XML Для сложных иерархий
Простые конфиги Properties Минимальный формат

© 2026 Igdrasil Project. Все права защищены.