首页 > 解决方案 > 包装 JSON 流

问题描述

我正在尝试将大型对象作为 gzip 压缩的 JSON 文本存储到 Azure blob。

我不想将序列化的数据保存在内存中,如果可以避免的话,我也不想假脱机到磁盘,但我不知道如何让它序列化和动态压缩。

我正在使用 Newtonsoft 的 JSON.NET(几乎是 .NET 的事实上的标准 JSON 序列化程序),但这些方法的签名似乎并不真正支持动态流。

Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob有一个UploadFromStream(Stream source, AccessCondition accessCondition = null, BlobRequestOptions options = null, OperationContext operationContext = null)方法,但为了让它正常工作,我需要让流的位置为 0,而 JsonSerializer.SerializeObject 不这样做。它只是作用于一个流,当它完成时,流位置在 EOF。

我想做的是这样的:

    public void SaveObject(object obj, string path, JsonSerializerSettings settings = null)
    {
        using (var jsonStream = new JsonStream(object, settings ?? _defaultSerializerSettings))
        using (var gzipStream = new GZipStream(jsonStream))
        {
            var blob = GetCloudBlockBlob(path);
            blob.UploadFromStream(gzipStream);
        }
    }

GZipStream...想法是,直到某些东西拉取数据(在这种情况下,直到被方法拉取才压缩数据) ,序列化才开始,blob.UploadFromStream()因此它保持低开销。它不需要是可搜索的流,它只需要按需读取。

我相信每个人都可以看到如果你从而System.IO.File.OpenRead()不是new JsonStream(object obj). 虽然它变得有点复杂,因为 Json.NET 需要“向前看”并可能填充缓冲区,但他们让它与CryptoStreamand一起工作,并且工作得非常顺利GZipStream

有没有办法做到这一点,不会将对象的整个 JSON 表示加载到内存中,或者先将其假脱机到磁盘只是为了反刍?如果 CryptoStreams 可以做到,我们应该可以用 Json.NET 来做,而不需要大量的努力。我会想。

标签: c#jsonstreamjson.net

解决方案


推荐阅读