mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 00:39:00 +08:00
- 实现UnifiedSettingsDataRepository统一管理所有设置数据 - 添加JsonSerializer基于Newtonsoft.Json的序列化功能 - 创建SettingsModel管理设置数据生命周期和迁移 - 添加完整的单元测试验证持久化功能 - 实现数据类型注册和批量保存加载功能 - 支持设置数据的版本迁移和事件通知机制
140 lines
4.2 KiB
C#
140 lines
4.2 KiB
C#
using Newtonsoft.Json;
|
|
using GameJsonSerializer = GFramework.Game.Serializer.JsonSerializer;
|
|
|
|
namespace GFramework.Game.Tests.Serializer;
|
|
|
|
[TestFixture]
|
|
public sealed class JsonSerializerTests
|
|
{
|
|
[Test]
|
|
public void Serialize_And_Deserialize_Should_RoundTrip_Object()
|
|
{
|
|
var serializer = new GameJsonSerializer();
|
|
var original = new PlayerStateStub
|
|
{
|
|
Name = "Player1",
|
|
Level = 7
|
|
};
|
|
|
|
var json = serializer.Serialize(original);
|
|
var restored = serializer.Deserialize<PlayerStateStub>(json);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(restored.Name, Is.EqualTo("Player1"));
|
|
Assert.That(restored.Level, Is.EqualTo(7));
|
|
});
|
|
}
|
|
|
|
[Test]
|
|
public void Serialize_Should_Honor_Injected_Settings()
|
|
{
|
|
var serializer = new GameJsonSerializer(new JsonSerializerSettings
|
|
{
|
|
Formatting = Formatting.Indented,
|
|
NullValueHandling = NullValueHandling.Ignore
|
|
});
|
|
|
|
var json = serializer.Serialize(new OptionalStateStub
|
|
{
|
|
Name = "Configured",
|
|
Description = null
|
|
});
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(json, Does.Contain(Environment.NewLine));
|
|
Assert.That(json, Does.Contain("\"Name\": \"Configured\""));
|
|
Assert.That(json, Does.Not.Contain("Description"));
|
|
});
|
|
}
|
|
|
|
[Test]
|
|
public void Converters_Should_Be_Used_For_Serialization_And_Deserialization()
|
|
{
|
|
var serializer = new GameJsonSerializer();
|
|
serializer.Converters.Add(new CoordinateStubConverter());
|
|
|
|
var json = serializer.Serialize(new CoordinateStub { X = 3, Y = 9 });
|
|
var restored = serializer.Deserialize<CoordinateStub>(json);
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(json, Is.EqualTo("\"3:9\""));
|
|
Assert.That(restored.X, Is.EqualTo(3));
|
|
Assert.That(restored.Y, Is.EqualTo(9));
|
|
});
|
|
}
|
|
|
|
[Test]
|
|
public void Deserialize_Should_Throw_With_Target_Type_Context_When_Json_Is_Invalid()
|
|
{
|
|
var serializer = new GameJsonSerializer();
|
|
|
|
var exception =
|
|
Assert.Throws<InvalidOperationException>(() => serializer.Deserialize<PlayerStateStub>("{invalid json}"));
|
|
|
|
Assert.Multiple(() =>
|
|
{
|
|
Assert.That(exception, Is.Not.Null);
|
|
Assert.That(exception!.Message, Does.Contain(typeof(PlayerStateStub).FullName));
|
|
Assert.That(exception.InnerException, Is.Not.Null);
|
|
});
|
|
}
|
|
|
|
[Test]
|
|
public void Deserialize_With_Runtime_Type_Should_Return_Target_Runtime_Type()
|
|
{
|
|
var serializer = new GameJsonSerializer();
|
|
|
|
var restored = serializer.Deserialize("{\"Name\":\"Runtime\",\"Level\":11}", typeof(PlayerStateStub));
|
|
|
|
Assert.That(restored, Is.TypeOf<PlayerStateStub>());
|
|
Assert.That(((PlayerStateStub)restored).Level, Is.EqualTo(11));
|
|
}
|
|
|
|
private sealed class PlayerStateStub
|
|
{
|
|
public string Name { get; set; } = string.Empty;
|
|
|
|
public int Level { get; set; }
|
|
}
|
|
|
|
private sealed class OptionalStateStub
|
|
{
|
|
public string Name { get; set; } = string.Empty;
|
|
|
|
public string? Description { get; set; }
|
|
}
|
|
|
|
private sealed class CoordinateStub
|
|
{
|
|
public int X { get; set; }
|
|
|
|
public int Y { get; set; }
|
|
}
|
|
|
|
private sealed class CoordinateStubConverter : JsonConverter<CoordinateStub>
|
|
{
|
|
public override void WriteJson(JsonWriter writer, CoordinateStub? value, JsonSerializer serializer)
|
|
{
|
|
writer.WriteValue($"{value?.X}:{value?.Y}");
|
|
}
|
|
|
|
public override CoordinateStub? ReadJson(
|
|
JsonReader reader,
|
|
Type objectType,
|
|
CoordinateStub? existingValue,
|
|
bool hasExistingValue,
|
|
JsonSerializer serializer)
|
|
{
|
|
var raw = (string?)reader.Value ?? throw new JsonSerializationException("Coordinate value cannot be null.");
|
|
var parts = raw.Split(':');
|
|
return new CoordinateStub
|
|
{
|
|
X = int.Parse(parts[0]),
|
|
Y = int.Parse(parts[1])
|
|
};
|
|
}
|
|
}
|
|
} |