c# 使用源生成进行序列化

在进行多平台发布时,经常需要进行剪裁,而基于反射进行的序列化/反序列化的类型会被剪裁掉,所以需要使用源生成进行序列化会很安全。原理与对象映射一样,对象映射工具 Mapperly

下面为基于 System.Text.Json 的源生成进行序列化的例子:如何在 System.Text.Json 中使用源生成

说明

  1. 创建一个需要序列化/反序列化的类
    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;
    }
  1. 创建一个源生成类
[JsonSerializable(typeof(TtsService.SavedLocale))]
internal partial class AppJsonContext : JsonSerializerContext {}
  1. 进行序列化/反序列化
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);
上一篇