正在分析来自服务器的UTF8 JSON响应

本文关键字:UTF8 JSON 响应 服务器 | 更新日期: 2023-09-27 18:26:32

我在解析来自服务器的JSON响应时遇到了一个奇怪的问题。在过去的几个月里,当得到响应时,它一直工作得很好(内容类型:text.html)通过这种方式:

string response = "";
using (var client = new System.Net.Http.HttpClient())
{
    var postData = new System.Net.Http.FormUrlEncodedContent(data);
    var clientResult = await client.PostAsync(url, postData);
    if(clientResult.IsSuccessStatusCode)
    {
        response = await clientResult.Content.ReadAsStringAsync();
    }
}
//Parse the response to a JObject...

但当收到内容类型为text/html的响应时;charset=utf8它抛出一个异常,即内容类型无效

Exception message: The character set provided in ContentType is invalid. Cannot read content as string using an invalid character set.

所以我改了这个:

response = await clientResult.Content.ReadAsStringAsync();

到此:

var raw_response = await clientResult.Content.ReadAsByteArrayAsync();
response = Encoding.UTF8.GetString(raw_response, 0, raw_response.Length);

现在我可以毫无例外地获得响应,但在解析它时,它会抛出解析异常。在调试过程中,我得到了以下信息:(出于测试目的,我将响应更改为较短的响应)

var r1 = await clientResult.Content.ReadAsStringAsync();
var r2 = Encoding.UTF8.GetString(await clientResult.Content.ReadAsByteArrayAsync(), 0, raw_response.Length);
System.Diagnostics.Debug.WriteLine("Length: {0} - {1}", r1.Length, r1);
System.Diagnostics.Debug.WriteLine("Length: {0} - {1}", r2.Length, r2);
//Output
Length: 38 - {"version":1,"specialword":"C'u00e3o"}
Length: 39 - {"version":1,"specialword":"C'u00e3o"}

JSON响应格式在这两种情况下似乎都是正确的,但长度不同,我不知道为什么。将其复制到记事本++以发现隐藏字符时,是否使用不知从哪里出现。

Length: 38 - {"version":1,"specialword":"C'u00e3o"}
Length: 39 - ?{"version":1,"specialword":"C'u00e3o"}

这个显然抛出了解析异常,但我不知道Encoding.UTF8.GetString为什么会导致这种情况。

在过去的几个小时里,我一直在与之斗争,我真的需要一些帮助。

正在分析来自服务器的UTF8 JSON响应

好吧,我很惊讶你会有这种行为,我本以为Encoding.UTF8.GetString会帮你处理的。

您看到的字符值0xFEFF是一个字节顺序标记("BOM")。BOM在UTF-8中是不必要的,因为字节顺序不是可变的,但它是允许的,因为它标记了以下文本是UTF-8编码的。(实际的字节序列是EF BB BF,但当以UTF-8解码时,它就变成了代码点FEFF。)

如果创建自己的UTF8Encoding实例,则可以告诉它是包含BOM表还是排除BOM表 (我想我错了,它可能只控制在编码时是否包括一个。)

或者,您可以明确测试并删除BOM(如果存在),例如:

var r2 = Encoding.UTF8.GetString(await clientResult.Content.ReadAsByteArrayAsync(), 0, raw_response.Length);
if (r2[0] == ''uFEFF') {
    r2 = r2.Substring(1);
}