jQuery序列化方法serialize,中文乱码之解决

缘由

整个网站的统一编码是GB2312,但是在一个页面中有一个表单的要提交的参数是根据条件动态生成的,所以使用了JQuery中的serialize()方法对所有参数进行封装,再提交到服务器。若提交的数据包含中文,服务器接到的数据中总会存在中文乱码。

过程

既然是中文乱码问题,就先从了解.Net中转码解码方式开始。以下内容来源自http://blog.sina.com.cn/s/blog_8e743a770101a3gr.html

中文转Unicode:HttpUtility.UrlEncodeUnicode(string str);

转换后中文格式:"%uxxxx" 举例:"柳_abc123" 转换结果是:"%u67f3_abc123"

Unicode转中文1:HttpUtility.UrlDecode(string str);

str格式:"%uxxxx" ,举例:"%u67f3_abc123"

Unicode转中文2:Regex.(string str);

str格式:"\uxxxx" ,举例:"\u67f3_abc123"

1.window.escape()与HttpUtility.UrlEncodeUnicode()编码格式一样:将一个汉字编码为%uxxxx格式

不会被window.escape编码的字符有:@ _ - . * / + 这与http://www.w3school.com.cn/js/jsref_escape.asp上的解释不符合

2.window.encodeURIComponent()与HttpUtility.UrlEncode()编码格式一样:将一个汉字编码为%xx%xx%xx的格式

不会被window.encodeURIComponent编码的字符有:'()*-._!~ 这与http://www.w3school.com.cn/js/jsref_encodeURIComponent.asp

解释相符合

不会被HttpUtility.UrlEncode编码的字符有:'()*-._!相比较而言,HttpUtility.UrlEncode比window.encodeURIComponent多

一个 ~ 编码

3.不会被window.encodeURI编码的字符有:-_.!*();/?:@&=$,# 与encodeURIComponent对比,

发现encodeURI不对:;/?:@&=+$,#这些用于分隔 URI 组件的标点符号进行编码

Asp.Net编码与JS编码的区别:

1. 不会被HttpUtility.UrlEncodeUnicode编码的字符与不会被HttpUtility.UrlEncode编码的字符一样,而escape和encodeURIComponent

不编码的字符不一样

2. HttpUtility.UrlEncode和HttpUtility.UrlEncodeUnicode会对/编码,而escape和encodeURIComponent会对/编码,encodeURI不会

对/编码

3. HttpUtility.UrlEncode()和HttpUtility.UrlEncodeUnicode()会把空格编码为 +,而escape,encodeURIComponent,encodeURI都

会将空格编码为

使用ajax提交一个字符串:

1. xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");

var postStr="val={name:'梅小伟',age:19}";

xmlHttp.send(postStr);

客户端发送请求如下:

POST /index.aspx HTTP/1.1

Accept: **

Accept-Language: zh-cn

Referer: http://localhost.:3910/Default.aspx

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727;

.NET CLR 3.0.04506.648;

.NET CLR 3.5.21022; CIBA; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; baiduie8)

Host: localhost.:3910

Content-Length: 59

Connection: Keep-Alive

Pragma: no-cache

val={name:'梅小伟',age:19}//发现这里使用了window.encodeURIComponent加码

在服务端index.aspx中打断点,发现Request.Form为:val={name:'%u6885%u5c0f%u4f1f',age:19}(这里居然使用了escape编码,

而不是encodeURIComponent编码),使用Request.Form[0]取出的值为“val={name:'梅小伟',age:19}”,使用Request.Form["val"]

取出的值为null(这是因为客户端发送请求时将=编码为=了,如果使用window.encodeURI这里就能取出Request.Form["val"]为:

“{name:'梅小伟',age:19}”了)

总结:不是使用get或者post,只要都是使用form的enctype属性的默认值application/x-www-form-urlencoded,所以如果你要传

的值都会经过window.encodeURIComponent()编码再传送(除了值包含空格不会被编码为 ,而是编码为+).传到服务器后,可以

用Server.UrlDecode()进行解码。但是要注意,不管是get方式还是post方式,enctype为application/x-www-form-urlencoded还

是multipart/form-data,用asp.net在后台查看Request.QueryString和Request.Form的时候,中文又变成了escape编码格式,例

如Request.Form=__VIEWSTATE=/wEPDwUJNzgzNDMwNTMzZGSvFy+l0lztppRS7QNr4qmrF4KTw==&mm=%u6556%u5fb7%u8428%u7684(英语

字母不会被编码,而一些符号使用encodeURIComponent和escape编码后相同,如=,$等等)。

为什么优先使用encodeURIComponent而不是escape?

escape方 法并不编码字符+。而我们知道,在用户提交的表单字段中,如果有空格,则会被转化为+字符,而服务器解析的时候则

会认为+号代表空格。由于这个缺 陷,escape方法并不能正确地处理所有的非ASCII字符,你应当尽量避免使用escape方法,取而

代之,你最好选择 encodeURIComponent()方法。

继续搜索一番,找到了问题的根源:serialize()方法自动调用了encodeURIComponent()方法将数据编码了,然而encodeURIComponent()在编码字符时,使用的是UTF-8编码。原帖也给出了解决方法,如下:

1、将jquery.js文件中的encodeURIComponent替换为encodeURI。即可解决中文乱码。

2、另一种方式将所有jsp、xml的字符集都设置为UTF-8 。

JSP <%@ page language="java" contentType="text/html; charset=UTF-8"%>

XML <?xml version="1.0" encoding="UTF-8"?>。

第一种方法好高大上,直接修改jQuery,对于我这种菜鸟显然行不通,而且会影响到其他所有的引用jquery.js文件的代码;第二种方法很直接很有效,很遗憾,网站使用GB2312编码格式自有它的道理,而且我只负责的也仅仅是这一个小模块,只对自己所负责模块的代码动刀是程序员行为准则之一。继续寻找解决方案。。。。

于是我在博客园中发现了它:http://www.cnblogs.com/fish-li/archive/2012/10/14/2723631.html非常全面的介绍了.Net中各种乱码出现的原因以及解决方案。于是直接搬到我的博客上,以便以后能随时拿来学习,便是上一篇转载的博客。里面对我所遇到问题的描述以及给出的解决方法如下:彻底解决encodeURIComponent()与GB2312乱码问题。又一个高大上!而且在原来页面的基础上,仅仅增加了一行代码!

beforeSend: function(xhr) {    xhr.setRequestHeader("x-charset", "utf-8"); },
膜拜啊!可是,服务端代码怎么写出来的?HttpModule是什么?HttpApplication、HttpWorkerRequest又是什么?这个类放到哪?怎么调用?对于还是菜鸟的我来说头好大啊!!

解决

在一次次的尝试并未解决问题后,我接了杯水,捋了捋烦躁的心情,将眼睛重新放到服务器接到的那几个中文乱码上,陷入迷游:本来是GB2312编码的、好好的中文汉字!被这个奇葩的serialize()按着UTF8编码,又被网站默认的GB2312解码,最终给了我一个魑魅魍魉一般的鬼汉字!艹!!

等等!这就是我的答案!在服务器上接收页面传参的部分对参数进行如下处理:

queryStr=context.Request["queryname"];
queryStr = HttpUtility.UrlDecode(HttpUtility.UrlEncode(queryStr, Encoding.GetEncoding("gb2312")), Encoding.UTF8);
很抱歉,我用了两行代码。