我从 web api 调用作为流接收响应,需要将其反序列化为模型。
这是一个通用方法,所以我不能说哪些代码部分会使用它以及响应负载是什么。
这是方法:
public async Task<T> InvokeAsync<T>(string method)
{
Stream response = await this.httpClientWrapper.InvokeAsync(method);
var serializer = new JsonSerializer();
using var streamReader = new StreamReader(response);
using var reader = new JsonTextReader(streamReader);
return serializer.Deserialize<T>(reader);
}
我正在尝试删除 Newtonsoft 并使用System.Text.Json API。
我在 Github 的 corefx 存储库中找到了这个移植指南,其中从 Stream/String 读取部分指出:
我们目前(从 .NET Core 3.0 预览版 2 开始)没有方便的 API 来直接(同步或异步)从流中读取 JSON。对于同步读取(尤其是小型有效负载),您可以将 JSON 有效负载读取到流的末尾到一个字节数组中并将其传递给阅读器
因此,遵循此建议,我提出以下建议:
public async Task<T> InvokeAsync<T>(string method)
{
Stream response = await this.httpClientWrapper.InvokeAsync(method);
var length = response.Length;
var buffer = ArrayPool<byte>.Shared.Rent((int)length);
var memory = new Memory<byte>(buffer);
await response.WriteAsync(memory);
var result = JsonSerializer.Deserialize<T>(memory.Span);
ArrayPool<byte>.Shared.Return(buffer);
return result;
}
所以我的问题是 - 我是否正确理解了建议,这是要走的路?
这个实现可能在很多方面都可以改进,但最困扰我的是从池中租用字节数组,例如Stream.Length
一个 long ,我将它转换为 int ,这可能会导致OverflowException
.
我试图研究System.IO.Pipelines并使用ReadOnlySequence<byte>
JSON API 的重载,但它变得非常复杂。