解决服务器返回JSON数据中文乱码问题

        还是编码的问题.

        下午试了一下谷歌搜索的 REST 服务, 接口是 "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=<search item>, 过程也很简单: 将你要搜索的内容经过 UrlEncode 之后代替<search item>, 然后发出一个 GET 请求, 就应该得到该搜索内容的 JSON 数据. 比如我搜索 "Create Chen", 在浏览器中可以看到返回如下数据:

{"responseData": {"results":[{"GsearchResultClass":"GwebSearch","unescapedUrl":"http://www.cnblogs.com/technology/","url":"http://www.cnblogs.com/technology/","visibleUrl":"www.cnblogs.com","cacheUrl":"http://www.google.com/search?q\u003dcache:wymiOeNCuYMJ:www.cnblogs.com","title":"\u003cb\u003eCreate Chen\u003c/b\u003e - 博客园","titleNoFormatting":"Create Chen - 博客园","content":"posted @ 2011-05-26 15:57 \u003cb\u003eCreate Chen\u003c/b\u003e 阅读(1206) | 评论(30) | 编辑 \u003cb\u003e...\u003c/b\u003e posted @ 2011-05-22 20:49 \u003cb\u003eCreate Chen\u003c/b\u003e 阅读(1781) | 评论(26) | 编辑

...省略以下内容...

        展示上一段的目的是为了说明在浏览器里, 数据包含中文的话, 还是显示正常的, 原因很简单: 我浏览器设置的默认编码就是 Unicode(UTF-8), 当然能正确显示中文.

        为了更好的展示数据, 我按照<Programming ASP.NET 3.5>里将在程序中获得的 JSON 数据序列化了一下, 没想到总是在序列化的时候出错, 只有搜索结果不包含中文的时候才运行正常. 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//...
//GoogleSearchResponse的一些构造
//...
 
protected void btnSearch_Click(object sender, EventArgs e)
{
    WebClient wc = new WebClient();
    Response.Write(wc.Encoding.ToString());
    wc.Headers.Add(HttpRequestHeader.Referer, Request.Url.ToString());
    string url = string.Format("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q={0}",
        Server.UrlEncode(txtSearchFor.Text));
    var json = wc.DownloadString(url);
    GoogleSearchResponse sechResponse = null;
    using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
    {
        DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(GoogleSearchResponse));
        sechResponse = jsonSerializer.ReadObject(ms) as GoogleSearchResponse;
    }
    StringBuilder sb = new StringBuilder();
    foreach (GoogleResult res in sechResponse.responseData.results)
    {
        sb.AppendFormat("<a href='{0}'>{1}</a><br />", res.unescapedUrl, res.title);
    }
    lblResults.Text = sb.ToString();
}

        经过调试发现在代码高亮的那一行, json字符串已经是乱码了. 因此我查看了 WebClient 的 DownloadString 方法:

        This method retrieves the specified resource. After it downloads the resource, the method uses the encoding specified in the Encoding property to convert the resource to a String. This method blocks while downloading the resource. To download a resource and continue executing while waiting for the server's response, use one of the DownloadStringAsync methods.

        前面两句说在下载到资源 (应该是 Byte[]) 后, 这个方法将会调用默认的编码方式将资源转化成 String. 好吧, 我来看看默认的编码方式是不是 UTF-8. 往往默认的编码方式是由操作系统和地区决定的, 在我的机器上测试后得知默认的编码方式不是 UTF-8, 是 System.Text.DBCSCodePageEncoding, 尽管编码方式不是 UTF-8, 但除了中文集字符, 这种编码方式确实还能识别出 Unicode 类型的编码, 前提是文件开头要有 BOM 信息, 关于能从 BOM 中获得哪些信息, 如下:

Unicode         0xFF, 0xFE
BE-Unicode    0xFE, 0xFF
UTF8        0xEF, 0xBB, 0xBF

        就是这样的一个对应关系, 但我发现服务器返回的 JSON 数据并没有这样的 BOM 信息:

        因此, 我需要在程序中设置一下 WebClient 的 Encoding 属性, 将它设为 Encoding.UTF8, 运行正常.

        但回过头来看看, 程序似乎在 DownloadString 方法中将下载到的 Byte[] 转成一个 String, 紧接着又将这个 String 转换成 Byte[] 存进内存中, 可以直接调用 DownloadData 方法的, 将 DownloadData 方法下载到的数据直接存储到内存中, 然后再做进一步的序列化处理, 这样就省去了两次类型转换的操作.

        关于编码, 前几天还看到了一个笑话, 也不知道是真的还是假的:

        以Windows中文版为例。从英文版移植到中文版,并不只是翻译菜单那么简单,许多源代码都得重新改写。比如Word里打完一行字会自动换行,可英文是单字节的,中文却是双字节,一个“好”字,就很可能“女”在上一行末尾,“子”却到了下一行开头。——唐骏 <我的成功可以复制> P89

posted @   Create Chen  阅读(48627)  评论(15编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示