我正面临一个从我的服务器解析JSON响应的奇怪问题。在过去几个月以这种方式获得响应(使用Content-Type: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...
但是当收到 Content-Type: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
。
在过去的几个小时里,我一直在与此斗争,我真的需要一些帮助。
答案 0 :(得分:8)
好吧,我很惊讶你得到了那种行为,我原本希望Encoding.UTF8.GetString
为你处理这个问题。
您所看到的,字符值0xFEFF
是字节顺序标记(“BOM”)。在UTF-8中不需要BOM,因为字节顺序不是可变的,但是允许的,作为以下文本编码为UTF-8的标记。 (实际的字节序列是EF BB BF,但是当它以UTF-8解码时,它变为代码点FEFF。)
如果您创建自己的 (我想我错了,它可能只能控制编码时是否包含一个。) UTF8Encoding
instance,您可以告诉它是否包含或排除BOM。
或者,您可以明确地测试并删除BOM(如果存在),例如:
var r2 = Encoding.UTF8.GetString(await clientResult.Content.ReadAsByteArrayAsync(), 0, raw_response.Length);
if (r2[0] == '\uFEFF') {
r2 = r2.Substring(1);
}