【问题标题】:Json to HttpContent using streams使用流的 Json 到 HttpContent
【发布时间】:2018-07-20 12:55:48
【问题描述】:

我有一个类 MyData,它可以使用 Json.Net JsonSerializer.Serialize(TextWriter, object) 进行 Json 序列化。我想通过HttpClient.PostAsync将此数据(作为json)发送到网络服务。

因为将 json 转换为字符串,然后将其作为 StringContent 发送(可能)性能不佳,所以我想用流来做。

我找到了StreamContent 类,它在其构造函数中接受了一个流。并且将 json 序列化为流也应该是可能的。所以我尝试了这个:

MyData data = ...; // already filled
string uri = ...;  // already filled
HttpClient client = new HttpClient();
JsonSerializer serializer = new JsonSerializer();
using (MemoryStream ms = new MemoryStream())
{
    using (StreamWriter sw = new StreamWriter(ms))
    using (JsonWriter jw = new JsonTextWriter(sw))
    {
        serializer.Serialize(sw, data);
        ms.Flush();
        ms.Position = 0;
    }
    HttpResponseMessage response = client.PostAsync(uri, new StreamContent(ms)).Result;
}

但运行此代码在HttpResponseMessage response = ... 行中给了我两个例外:

  1. HttpRequestException:将内容复制到流中时出错。
  2. ObjectDisposedException:无法访问已关闭的流。

我做错了什么?

【问题讨论】:

    标签: c# serialization stream json.net httpclient


    【解决方案1】:

    如果将对象序列化为MemoryStream,则整个 JSON 数据将写入缓冲区,因此与仅序列化为字符串并使用 StringContent 相比,没有显着的性能优势。

    【讨论】:

    • 所以我想我应该使用缓冲流?
    • 缓冲流只是另一个流之上的一层,所以它不会有用。在 .NET Core 2.1 中,您可以使用 pipelines。但这实际上只会对大型 JSON 文件(几兆字节)或非常热的路径产生影响。
    【解决方案2】:

    您的 StremWriter 在发送请求之前处理内存流,这就是您收到异常的原因。 您可以将 using 语句移动到与 MemoryStream 相同的范围内,或者使用 StreamWriter 的构造函数接受一个布尔参数,以便在释放 writer 后保持流打开。

    StreamWriter constructor:

    除非您将 leaveOpen 参数设置为 true,否则 StreamWriter 对象会在调用 StreamWriter.Dispose 时对提供的 Stream 对象调用 Dispose()。

    【讨论】:

      猜你喜欢
      • 2015-09-10
      • 1970-01-01
      • 2012-06-24
      • 2021-07-17
      • 2015-01-12
      • 2014-04-23
      • 2014-05-06
      • 1970-01-01
      相关资源
      最近更新 更多