在进行多平台发布时,经常需要进行剪裁,而基于反射进行的序列化/反序列化的类型会被剪裁掉,所以需要使用源生成进行序列化会很安全。原理与对象映射一样,对象映射工具 Mapperly
下面为基于 System.Text.Json 的源生成进行序列化的例子:如何在 System.Text.Json 中使用源生成
说明
- 创建一个需要序列化/反序列化的类
public class SavedLocale
{
public string Language { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string Id { get; set; } = string.Empty;
public string Country { get; set; } = string.Empty;
}
- 创建一个源生成类
[JsonSerializable(typeof(TtsService.SavedLocale))]
internal partial class AppJsonContext : JsonSerializerContext {}
- 进行序列化/反序列化
JsonSerializer.Deserialize(json, AppJsonContext.Default.SavedLocale);
JsonSerializer.Serialize(value, AppJsonContext.Default.SavedLocale)
例子
准备序列化类
public class SavedLocale
{
// 为了方便使用,将 JsonTypeInfo 添加到 SavedLocale 类中
public static readonly JsonTypeInfo<SavedLocale> JsonTypeInfo = AppJsonContext.Default.SavedLocale;
public string Language { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string Id { get; set; } = string.Empty;
public string Country { get; set; } = string.Empty;
}
创建 JsonSerializerContext 类
该类必须在顶层,可以作为公用类,放在 Serialization 命名空间下,需要序列化/反序列化的类在 AppJsonContext 上进行注册
# 创建 JsonSerializerContext 类,可作为公用类,需要序列化/反序列化的类在 AppJsonContext 上进行注册
// [JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(TtsService.SavedLocale))]
internal partial class AppJsonContext : JsonSerializerContext {}
序列化/反序列化辅助类
# 序列化 / 反序列化辅助类
public static class ObjectExtensions {
/// 进行反序列化
public static T ? FromJson < T > (this string ? json, JsonTypeInfo < T > typeInfo) {
if (json == null) {
return default;
}
var obj = JsonSerializer.Deserialize < T > (json, typeInfo);
return obj;
}
/// 仅在 debug 时使用, 如果有剪裁类时,可能会返回 {} 或是直接抛出异常
public static string ToDebugJson(this object ? obj, bool beautify = false) {
if (obj == null) {
return string.Empty;
}
try {
JsonSerializerOptions options = new() {
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, // 允许所有 Unicode 字符不转义
WriteIndented = beautify, // 如果需要美化排版
};
// 将对象序列化为 JSON 字符串
var jsonString = JsonSerializer.Serialize(obj, options);
return jsonString;
} catch (Exception e) {
return $ "Serialize Error, {obj.GetType().Name}: {e.Message}";
}
}
/// 进行序列化
public static string ToJson < T > (this T value, JsonTypeInfo < T > typeInfo) {
// 这样直接把 typeInfo 传进去,避开了内部再去查表的过程
return JsonSerializer.Serialize(value, typeInfo);
}
}
使用
# 使用
var json = obj.ToJson(SavedLocale.JsonTypeInfo);
var obj = json.FromJson(SavedLocale.JsonTypeInfo);