c# - JToken.WriteToAsync 不能正确写入流
问题描述
我想将 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
:
返回提供 Unicode 字节顺序标记 (BOM) 的 UTF8Encoding 对象。
?
您看到的额外内容是 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)
. 因此,您的代码应如下所示:
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在这里。
推荐阅读
- python - Matplotlib.plot() 不会正确渲染绘图。改为制作某种网络
- javascript - 将文档添加到 Firestore 中不存在的子集合
- http - 使用 curl 进行 nutch RESTapi 调用时出错
- python - 如何在不使用 json 库或在字典或列表中没有任何其他库的情况下读取 json 文件?
- vbscript - Global.asa 上的 Session_OnEnd 事件,并发问题
- sql - 如何使用户表对不同类型的用户通用?否则我是否需要根据 laravel 中的用户更改用户注册表?
- angular - 如何在Angular2-multiselect中显示选中的复选框计数?
- php - php laravel artisan 迁移模型中的错误?
- javascript - 如何比较价值
- javascript - 使用 pg-promise 执行接受参数数组的 Postgresql 函数