【发布时间】:2020-02-19 02:00:12
【问题描述】:
我正在以流形式接收来自 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 存储库中找到了这个 porting guide,其中 Reading from a Stream/String 部分指出:
我们目前(截至 .NET Core 3.0 预览版 2)没有方便的 直接从流中读取 JSON 的 API(同步或 异步)。对于同步阅读(尤其是小 有效负载),您可以读取 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 很长,我将其转换为 int 可能会导致 OverflowException。
我试图研究 System.IO.Pipelines 并使用 JSON API 的 ReadOnlySequence<byte> 重载,但它变得非常复杂。
【问题讨论】:
标签: c# json .net-core system.text.json