将MemoryStream转换为JSON字符串

3
我在使用MemoryStream管理字符串时遇到了困难。具体来说,我正在尝试使用JSON,但是不使用内置的序列化/反序列化方法。当使用NewtonSoft JSON编写器时,它相当简单,因为它需要一个TextWriter,所以编写类似于以下内容的东西非常简单:(然后是一段示例代码)
        StringBuilder sb = new StringBuilder();
        StringWriter sw = new StringWriter(sb);
        using (newton.JsonWriter writer=new newton.JsonTextWriter(sw))
        {
            writer.WriteStartObject();
            writer.WritePropertyName("Name");
            writer.WriteValue("Neil");
            writer.WriteEnd();
            writer.Flush();
            System.Console.WriteLine(sb.ToString());
        }

但是当我尝试使用新的 .net Core 3.x 时,它不再接受 TextWriter,而是需要 Stream 或 IBufferWriter。由于不太清楚如何使用 IBufferWriter,我唯一能想到的方法是以下这种方式将流转换为字符串,与之相比似乎有些笨拙。除了设置位置、创建新的读取器并读取到结尾之外,是否有更好的方法呢?

要么找到更好的将内存流转换为字符串的方法,要么使用 IBufferWriter?

        MemoryStream ms = new MemoryStream();
        System.Text.Json.Utf8JsonWriter writer = new Utf8JsonWriter(ms);
        writer.WriteStartObject();
        writer.WritePropertyName("Name");
        writer.WriteStringValue("Neil");
        writer.WriteEndObject();
        writer.Flush();
        ms.Position = 0;
        string output = new StreamReader(ms).ReadToEnd();
        Console.WriteLine(output);

谢谢。

2个回答

3

你可以直接调用内存流的 ToArray 方法将其转换为 UTF-8 字节的数组,随后可以使用 Encoding.UTF8.GetString 将其转换为字符串:

var ms = new MemoryStream();
Utf8JsonWriter writer = new Utf8JsonWriter(ms);
writer.WriteStartObject();
writer.WritePropertyName("Name");
writer.WriteStringValue("Neil");
writer.WriteEndObject();
writer.Flush();
ms.Close();
Console.WriteLine(System.Text.Encoding.UTF8.GetString(ms.ToArray()));

谢谢。相比于写入器,流的好处是什么?另一种方式似乎更容易。顺便说一下,我找不到关于 IBufferWriter 的任何文档。 - undefined
@Neil 你也可以创建一个 ArrayBufferWriter<byte> 来进行写入操作。然后你可以使用 WrittenMemory.ToArray() 方法来获取 UTF 8 字节数组。我对于 IBufferWriter 的了解也不多,只知道它是一个较新的 API,这就是为什么我在我的回答中使用了 MemoryStream - undefined

2

可以通过使用Microsoft.IO.RecyclableMemoryStream库来实现内存高效的方法,该库提供了一个RecyclableMemoryStream类型,实现了IBufferWriter和一个方便的GetReadOnlySequence方法,通过不必调用ToArray来避免分配新数组。

以下代码使用该库与您的最后一个示例:

using Microsoft.IO;
using System.Buffers;
using System.Text;
using System.Text.Json;

...
// Declare this as a field of your class.
private static readonly RecyclableMemoryStreamManager Manager = new RecyclableMemoryStreamManager();
...

using (var ms = (RecyclableMemoryStream)Manager.GetStream())
{
    using (var writer = new Utf8JsonWriter((IBufferWriter<byte>)ms))
    {
        writer.WriteStartObject();
        writer.WritePropertyName("Name");
        writer.WriteStringValue("Neil");
        writer.WriteEndObject();
    }

    var output = Encoding.UTF8.GetString(ms.GetReadOnlySequence());
    Console.WriteLine(output);
}

Encoding.GetString 方法接受一个 ReadOnlySequence<byte>,是由 EncodingExtensions 提供的扩展方法,可在 .NET 5+ 上使用。

RecyclableMemoryStream 还提供了一个 GetSpan 方法,当上述扩展方法不可用时可以使用,此时需要对围绕 Encoding.UTF8.GetString 的代码进行一些调整,以提供一个 Span<byte>

ms.Position = 0;
Encoding.UTF8.GetString(ms.GetSpan().Slice(0, (int)ms.Length))

关于使用和配置此库的更多细节,我建议您查看其文档


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接