【问题标题】:How to deserialize JSON text on the fly in C#如何在 C# 中动态反序列化 JSON 文本
【发布时间】:2021-07-26 00:57:37
【问题描述】:

我正在从一个异步函数读取/接收字节块,我将其缓冲在 MemoryStream 中,然后反序列化为 C# 对象。

    public async Task<Message> Read()
    {
        byte[] block = new byte[1024];
        int bytesRead;

        using var ms = new MemoryStream();
        while ((bytesRead = await GetBlock(block)) > 0)
        {
            ms.Write(block, 0, bytesRead);
        }
        ms.Seek(0, SeekOrigin.Begin);
        var result = await System.Text.Json.JsonSerializer.DeserializeAsync<Message>(ms);
        return result;
    }

我更喜欢一种不会缓冲整个数据并在内存中保留潜在大字节数组的方法。就像一个 Dummy-Stream 一样,它将每个字节块转发到 Desirailize 函数,因为它正在被 GetBlocks 函数接收。

    public async Task<Message> Read()
    {
        byte[] block = new byte[1024];
        int bytesRead;

        using var rs = new RedirectStream((rs) =>
        {
            while ((bytesRead = await GetBlock(block)) > 0)
            {
                rs.Write(block, 0, bytesRead);
            }
        });

        var result = await System.Text.Json.JsonSerializer.DeserializeAsync<Message>(rs);
        return result;
    }

这样的流类是否存在,或者我需要创建自己的(如果是的话 - 我从哪里开始?)。

除此之外,了解 DeserializeAsync 函数是否能够充分利用这种机制(意味着在实际开始反序列化之前不将流读取到末尾)会很有趣。

【问题讨论】:

  • 您是否收到多个单独的对象?还是只有一个大物体?
  • 只有一个大对象

标签: c# json stream .net-5 system.text.json


【解决方案1】:

这样的流类存在吗

据我所知,标准库中没有与您的RedirectStream 类似的东西,因此您可能必须自己实现它,like other folks already did。搜索 NuGet 包不会给出相关的结果(例如 https://github.com/MarcusChr/BlockBasedMemoryStream,其中 removeReadData 放错了位置,无法在您的情况下使用)。

[Does] DeserializeAsync 函数甚至可以很好地利用这种机制

实际版本的JsonSerializer.DeserializeAsync 使用Stream.ReadAsync 方法,您可以从the sources 中看到。所以是的,就目前而言(不太可能出现回归)。

【讨论】:

  • SlidingStream 是一个比 RedirectStream 更好的名字 :) 太糟糕了,它不是标准库的一部分,但我应该能够从链接的帖子中获得灵感来创建自己的
  • 这是你的宝贝,你选择名字;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-13
  • 2021-09-14
  • 2015-12-05
  • 1970-01-01
  • 2020-03-16
  • 1970-01-01
相关资源
最近更新 更多