c# 高并发下使用 System.Text.Json 的 JsonSerializerContext 提升性能

10次阅读

jsonSerializerContext通过预编译序列化逻辑、避免反射与锁竞争、实现线程安全零分配来提升高并发性能;需继承基类、用[jsonSerializable]标记类型、启用源生成,并复用静态实例配合泛型api调用

c# 高并发下使用 System.Text.Json 的 JsonSerializerContext 提升性能

为什么 JsonSerializerContext 能在高并发下提升性能

因为 JsonSerializerContext 预编译了类型序列化逻辑,避免每次调用 JsonSerializer.Serialize 时重复反射、生成委托、构建缓存键。在高并发场景下,反复创建 JsonSerializerOptions 或依赖默认上下文会触发锁竞争和 GC 压力,而静态复用的 JsonSerializerContext 子类是线程安全且零分配(对已知类型)。

如何正确定义和使用 JsonSerializerContext 子类

必须继承抽象基类 JsonSerializerContext,用 [JsonSerializable] 标记要支持的类型,并启用源生成(Source Generator)。不能手动 new 它,也不能把它当普通类随意实例化。

  • 项目需启用源生成:在 .csproj 中添加 true.net 7+ 推荐),或显式引用 System.Text.Json.SourceGeneration
  • JsonSerializerContext 子类必须是 public sealed,且构造函数internalprotected
  • 每个上下文应聚焦一组相关类型,避免把几十个 DTO 全塞进一个上下文——类型过多会导致生成代码膨胀、编译变慢、热重载失败
public Static partial class MyJsonContext : JsonSerializerContext {     [JsonSerializable(typeof(Order))]     [JsonSerializable(typeof(List))]     [JsonSerializable(typeof(Dictionary))]     public static partial JsonTypeInfo Order { get; }     public static partial JsonTypeInfo> OrderList { get; } }

高并发中怎么传参、怎么选 API

核心原则:复用同一个 JsonSerializerContext 实例,且优先使用泛型重载,避免运行时类型擦除带来的装箱或反射回退。

  • 序列化时用 JsonSerializer.Serialize(output, value, context.Order),而不是 JsonSerializer.Serialize(output, value, options) —— 后者绕过源生成,退化为传统路径
  • 反序列化必须指定具体 JsonTypeInfo,例如 JsonSerializer.Deserialize(input, MyJsonContext.Order);若只传 context 不传 JsonTypeInfo,会触发内部查找逻辑,失去性能优势
  • 不要在请求处理中 new 上下文实例:所有 JsonSerializerContext 子类都应通过静态属性暴露,如 MyJsonContext.default 或直接用生成的 static partial 属性

容易被忽略的坑和兼容性限制

源生成不是万能的,很多动态场景它不支持,强行用反而引发运行时异常或静默退化。

  • 不支持运行时才确定的泛型参数(如 T 来自方法参数且未在 [JsonSerializable] 中声明)
  • 不支持 ObjectdynamicExpandoObject 等无固定结构类型——它们仍走反射路径,且无法被 JsonSerializerContext 捕获
  • .NET 6 的源生成是实验性功能,.NET 7+ 才稳定;若项目混用旧版 SDK 或 CI 环境未升级,可能生成失败但不报错,导致上线后性能骤降
  • 调试时注意:生成的代码在 obj/Debug/... 下,若清理不彻底,可能引用旧版 JsonTypeInfo 导致序列化结果不一致

最常出问题的是「以为加了 [JsonSerializable] 就万事大吉」,实际没检查生成是否成功、没验证泛型绑定是否精确、也没压测对比分配率——这些地方一漏,高并发下的性能收益就归零。

text=ZqhQzanResources