JToken.WriteToAsync dosen't write to streaming to version



我想异步地将一个JToken写入流。我提到了JToken.WriteToAsync不向JsonWriter写入。然而,流输出是?[],而ToString()输出是[]。为什么流在开头包含额外的字节?

我的代码如下:

static async Task Main(string[] args)
{
JArray arr = new JArray();
//var c = JToken.FromObject("abc");
//arr.Add(c);
var stream = new MemoryStream();
await using (var requestWriter = new StreamWriter(stream, System.Text.Encoding.UTF8, leaveOpen: true))
{
var jsonWriter = new JsonTextWriter(requestWriter); 
try
{
await arr.WriteToAsync(jsonWriter);
}
finally
{
await jsonWriter.CloseAsync();
}
Console.WriteLine(System.Text.Encoding.UTF8.GetString(stream.GetBuffer(), 0, checked((int)stream.Length)));
Console.WriteLine(arr.ToString());
}
}

为什么流输出不正确?Json.net的版本是13.0.1。

摘要

您的问题与异步写入无关。您的问题是Encoding.UTF8:

返回一个UTF8Encoding对象,该对象提供Unicode字节顺序标记(BOM(。

您看到的额外?就是BOM。为了防止BOM表被写入,在写入时使用new UTF8Encoding(false)。或者,您可以只执行new StreamWriter(stream, leaveOpen: true),因为默认情况下,StreamWriter构造函数将使用不带字节顺序标记(BOM(的UTF-8编码

详细信息

您的问题可以更简单地复制如下:

JArray arr = new JArray();
var stream = new MemoryStream();
using (var requestWriter = new StreamWriter(stream, System.Text.Encoding.UTF8, leaveOpen: true))
using (var jsonWriter = new JsonTextWriter(requestWriter))
{
arr.WriteTo(jsonWriter);
}
var resultJson = Encoding.UTF8.GetString(stream.GetBuffer(), 0, checked((int)stream.Length));
Console.WriteLine(BitConverter.ToString(stream.GetBuffer(), 0, checked((int)stream.Length)));
Console.WriteLine(resultJson);
Console.WriteLine(arr.ToString());
Assert.AreEqual(arr.ToString(), resultJson);

断言失败,并显示以下消息:

NUnit.Framework.AssertionException:   Expected string length 2 but was 3. Strings differ at index 0.

BitConverter.ToString()的输出如下:

EF-BB-BF-5B-5D

在这里演示小提琴。

5B-5D是括号,但EF-BB-BF的三个前导字符是什么?快速搜索显示它是UTF-8字节顺序标记。由于RFC 8259规定实现不得在网络传输的JSON文本的开头添加字节顺序标记(U+FEFF(,因此应使用new UTF8Encoding(false)省略BOM。因此,您的代码应该看起来像:

JArray arr = new JArray();
var stream = new MemoryStream();
await using (var requestWriter = new StreamWriter(stream, new UTF8Encoding(false), leaveOpen: true))
{
var jsonWriter = new JsonTextWriter(requestWriter); 
try
{
await arr.WriteToAsync(jsonWriter);
}
finally
{
await jsonWriter.CloseAsync();
}
}
var resultJson = Encoding.UTF8.GetString(stream.GetBuffer(), 0, checked((int)stream.Length));
Console.WriteLine(BitConverter.ToString(stream.GetBuffer(), 0, checked((int)stream.Length)));
Console.WriteLine(resultJson);
Console.WriteLine(arr.ToString());
Assert.AreEqual(arr.ToString(), resultJson);

在这里演示小提琴#2。

最新更新