mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-07 00:39:00 +08:00
- 更新 Godot 与教程细页的 reader-facing 采用说明 - 修复旧文档、ai-libs 与内部术语在公开页面中的暴露 - 更新文档治理恢复点并记录接近阈值的停止状态
4.7 KiB
4.7 KiB
title, description
| title | description |
|---|---|
| 序列化系统 | 以当前 GFramework.Game.JsonSerializer 与 JsonSerializerTests 为准,说明 JSON 序列化器的配置生命周期和使用边界。 |
序列化系统
GFramework.Game 当前在序列化这一层的默认公开入口只有 JsonSerializer。
它实现的是:
ISerializerIRuntimeTypeSerializer
它不负责:
- schema 驱动配置生成
- 存档槽位管理
- 文件路径或目录布局
这些能力分别属于 source generator、repository 和 storage。
当前公开入口
JsonSerializer
JsonSerializer 基于 Newtonsoft.Json,既支持泛型 API,也支持运行时类型 API:
using GFramework.Core.Abstractions.Serializer;
using GFramework.Game.Serializer;
ISerializer serializer = new JsonSerializer();
IRuntimeTypeSerializer runtimeSerializer = new JsonSerializer();
当前测试覆盖的核心行为包括:
- 普通对象可正常 round-trip
- 注入的
JsonSerializerSettings会直接生效 Settings与Converters暴露的是同一个活动配置实例- 运行时类型序列化 / 反序列化可处理
object + Type - 非法 JSON 会抛出带目标类型上下文的
InvalidOperationException - 非法参数(例如空字符串)会保留
ArgumentException - 运行时类型序列化允许
null,输出"null"
配置生命周期
这里最需要先确认的是序列化器的配置生命周期。
JsonSerializer 不会复制你传入的 JsonSerializerSettings。它会直接持有并复用这份实例,以及里面的 Converters 集合。
这意味着推荐模式是:
- 在组合根创建序列化器
- 一次性完成 settings / converters 配置
- 再把同一个实例注册给存储、repository 或 architecture
推荐写法:
using Newtonsoft.Json;
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore
};
settings.Converters.Add(new CoordinateConverter());
var serializer = new JsonSerializer(settings);
不推荐写法:
var serializer = architecture.GetUtility<IRuntimeTypeSerializer>();
// 序列化器已经被多个组件共享后,再继续改 converter,容易让并发调用看到不稳定配置。
((JsonSerializer)serializer).Converters.Add(new LateBoundConverter());
最小接入路径
作为底层 serializer 注册
当前更常见的采用方式不是“业务代码直接到处调 serializer”,而是把它注册给存储和 repository 复用:
using GFramework.Core.Abstractions.Serializer;
using GFramework.Game.Serializer;
var serializer = new JsonSerializer();
architecture.RegisterUtility<ISerializer>(serializer);
architecture.RegisterUtility<IRuntimeTypeSerializer>(serializer);
然后由:
FileStorageUnifiedSettingsDataRepository- 其他依赖
ISerializer/IRuntimeTypeSerializer的组件
统一复用这一份实例。
直接处理运行时类型
当业务层拿到的是 object + Type 组合,而不是静态泛型类型时,再使用运行时 API:
var serializer = new JsonSerializer();
object data = new PlayerState
{
Name = "Runtime",
Level = 11
};
var json = serializer.Serialize(data, data.GetType());
var restored = serializer.Deserialize(json, data.GetType());
与存储系统的关系
FileStorage 已经会调用注入的 ISerializer 自己完成对象读写,因此当前默认接法里:
- 你可以直接
storage.WriteAsync("profile/player", profile) - 不需要先手工
serializer.Serialize(profile)再把字符串写回存储
手工显式调用 Serialize(...) 更适合这些场景:
- 需要把 JSON 发到网络或日志
- 需要和外部文本格式做中转
- 需要直接调试序列化输出内容
如果目标只是本地持久化,优先让 IStorage / repository 复用 serializer。
与配置系统的关系
不要把 JsonSerializer 和 Game 的 YAML 配置系统混在一起:
JsonSerializer- 负责运行时对象 JSON 序列化
Game.SourceGenerators + YamlConfigLoader- 负责 schema 驱动的配置表生成与 YAML 读取
如果你的目标是静态内容配置表,而不是运行时持久化对象,请改看 配置系统。
当前边界
- 当前公开默认实现只有 JSON,没有内建 MessagePack、Binary 或 ProtoBuf 实现
JsonSerializer负责序列化,不负责对象版本迁移;版本迁移属于SettingsModel<TRepository>或SaveRepository<TSaveData>- 序列化器共享后应视为只读配置对象,避免在运行期继续修改 settings / converters