.NET 6 中 System.Text.Json 对 IAsyncEnumerable 的序列化支持解析
docs This repository contains .NET Documentation. 项目地址: https://gitcode.com/gh_mirrors/docs2/docs
前言
在 .NET 6 中,System.Text.Json 序列化库迎来了一个重要更新 - 新增了对 IAsyncEnumerable 接口的序列化支持。这一变化为异步数据流的处理带来了更好的支持,特别是在 ASP.NET Core MVC 中处理流式响应时尤为有用。
IAsyncEnumerable 简介
IAsyncEnumerable 是 .NET Core 3.0 引入的异步可枚举接口,它允许开发者以异步方式消费数据流。与传统的 IEnumerable 不同,IAsyncEnumerable 的 MoveNextAsync 方法是异步的,这使得它特别适合处理来自数据库、网络请求等异步数据源的数据。
变更内容详解
旧版行为
在 .NET 6 之前的版本中,System.Text.Json 对 IAsyncEnumerable 的处理存在以下限制:
- 序列化时会将 IAsyncEnumerable
实例转换为空 JSON 对象
{}
- 反序列化时会抛出 JsonException 异常
新版行为
.NET 6 中对此进行了重大改进:
- 异步序列化方法(如 SerializeAsync)现在能够正确枚举 IAsyncEnumerable 实例,并将其序列化为 JSON 数组
- 同步序列化方法(如 Serialize)仍然不支持 IAsyncEnumerable ,调用时会抛出 NotSupportedException
- 反序列化现在能够正确处理 JSON 数组到 IAsyncEnumerable 的转换
实际应用场景
这一改进特别适用于以下场景:
- ASP.NET Core MVC 控制器:现在可以直接返回 IAsyncEnumerable 类型的结果,框架会自动处理流式响应
- 数据库查询结果:如使用 Entity Framework Core 的异步查询结果可以直接序列化
- 实时数据流:处理来自消息队列或其他实时数据源的异步数据流
兼容性影响
这一变更属于源代码兼容性变更。虽然重新面向 .NET 6 不会导致编译错误,但运行时行为可能发生变化:
- 之前被序列化为
{}
的 IAsyncEnumerable 现在会被序列化为数组 - 反序列化现在能够成功,而之前会抛出异常
最佳实践建议
需要保留旧行为的情况
如果您的应用依赖于 IAsyncEnumerable 被序列化为空对象的行为,可以通过以下方式禁用新行为:
- 使用 JsonIgnore 特性:标记不需要序列化的属性
[JsonIgnore]
public IAsyncEnumerable<Data> DataStream { get; set; }
- 自定义转换器:创建一个将 IAsyncEnumerable 序列化为空对象的转换器
public class AsyncEnumerableEmptyObjectConverter : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
return typeToConvert.IsGenericType &&
typeToConvert.GetGenericTypeDefinition() == typeof(IAsyncEnumerable<>);
}
public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options)
{
var converterType = typeof(AsyncEnumerableEmptyObjectConverter<>)
.MakeGenericType(type.GetGenericArguments()[0]);
return (JsonConverter)Activator.CreateInstance(converterType);
}
}
public class AsyncEnumerableEmptyObjectConverter<T> : JsonConverter<IAsyncEnumerable<T>>
{
public override IAsyncEnumerable<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotSupportedException();
}
public override void Write(Utf8JsonWriter writer, IAsyncEnumerable<T> value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteEndObject();
}
}
性能考虑
当处理大型异步数据流时,直接序列化可能会导致内存压力增加。在这种情况下,建议:
- 考虑分批处理数据
- 使用流式处理方式,而不是一次性加载所有数据
总结
.NET 6 中对 IAsyncEnumerable 的序列化支持是一个重要的改进,它为异步数据流的处理提供了更好的支持。开发者应当评估这一变更对现有应用的影响,并根据需要采取适当的兼容性措施。对于新项目,这一特性将大大简化异步数据流的处理流程。
docs This repository contains .NET Documentation. 项目地址: https://gitcode.com/gh_mirrors/docs2/docs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考