【问题标题】:Parsing UTF8 JSON response from server解析来自服务器的 UTF8 JSON 响应
【发布时间】:2013-08-05 06:32:41
【问题描述】:

我在解析来自服务器的 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 会抛出Content-Type is invalid的异常。

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 响应格式在这两种情况下似乎都是正确的,但长度不同,我不知道为什么。将其复制到 notepad++ 以发现隐藏字符时,一个 ? 不知从何而来。

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

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

过去几个小时我一直在与这个问题作斗争,我真的需要一些帮助。

【问题讨论】:

  • @T.J.Crowder text/html; charset=utf8 抱歉耽搁了。我再次进行了测试以确保
  • @T.J.Crowder 第一个字符:FEFF

标签: c# .net json http utf-8


【解决方案1】:

嗯,我很惊讶你会出现这种行为,我原以为 Encoding.UTF8.GetString 会为你处理这个问题。

您所看到的字符值0xFEFF 是一个字节顺序标记(“BOM”)。 BOM 在 UTF-8 中是不必要的,因为字节顺序不是可变的,但它允许的,作为以下文本编码为 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);
}

【讨论】:

  • 用简单的字符串替换?以后会不会出现这样的不同角色?
  • @letiagoalves:根据定义,对于 UTF-8,只有一个允许的 BOM,即您遇到的那个。我可能会使用Substring 而不是Replace。 BOM 将仅作为第一个字符出现。更多关于 BOM 和 unicode here.
  • +1 感谢您的帮助。我改用TrimStart('\uFEFF');
猜你喜欢
  • 2011-02-10
  • 1970-01-01
  • 2013-02-13
  • 2014-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
相关资源
最近更新 更多