Jquery Json怎么都搞不定,求解整体解决方案

nmbtzzg 发布于 2011/06/11 10:51
阅读 6K+
收藏 1

各位大侠,下面一段代码,头疼了两个星期,各种方法都试了,就是得不到正解。求助完整代码方案。

(注意:我已经知道汉字需要urlencode(iconv(“变量”)),然后json_encode()了,也知道dataType:"json"需要严格的数据格式了{“a”:“a值”,“b”:“b值”},但就是不能成功返回查询数据,并追加到select框。总是undefind,恼人啊!!!)

JS代码:

...

$.ajax({
             type: "GET",
             url: "select_branch.php" ,
             data: { "region":$("#bg_region").val(),"kind":$("#bg_kind").val() },
             dataType: "json",
             complete :function(){ alert("The progream is complete!!!"); },
             error: function() { alert("Jquery Ajax request 發生錯誤"); },
             success: function(data)
               { 
                  var s_data=decodeURIComponent(data); 
                  $("#bg_branch").empty();

                  $.each(s_data, function(i,n){$("#bg_branch").append("<option value="+s_data[i].branch+">"+s_data[i].branch+"</option>");});
                     } 
              });

PHP代码:

<?php
    include ('../../conn_xxjsj.php');
    $init_region=iconv("gb2312","utf-8",$_GET['region']);
    $init_kind=iconv("gb2312","utf-8",$_GET['kind']);
    $init_sql="select branch from xxjsj."+$init_kind+" where region='"+$init_region+"' ";
    $init_query=@mysql_query($init_sql,$conn);
    while($init_row=@mysql_fetch_array($init_query))
      {
         $response=array('branch'=>rawurlencode(urlencode(iconv("gb2312", "utf-8", $init_row['branch']))));
          echo json_encode($response); 
      }
   echo json_encode($response);
   @mysql_free_result($init_query);
   @mysql_close($conn);
 ?>

以下是问题补充:

@nmbtzzg:这也是从网上学的,应该也不用eval()了吧?但是就是不行啊!!!哥们,再给看看。 (2011/06/11 11:02)
@nmbtzzg:改成POST方式,也去掉了decodeURIComponent(data); 还是undefined,晕死了!!! (2011/06/11 11:05)
加载中
1
mark35
mark35
看了下楼主代码,发现很多问题:

1、ajax使用的只能是UTF-8编码,你在后台接收到前台通过ajax提交的值要么是utf-8编码要么是纯ASCII(在任何编码格式下都不会发生变化),所以你在后台做
$init_region=iconv("gb2312","utf-8",$_GET['region']);
$init_kind=iconv("gb2312","utf-8",$_GET['kind']); 

是错误的——要么因为接收到是UTF-8编码而直接使用,要么因为前台用GB编码而对汉字进行包装(是WRAP打包,比如encodeURIComponent,而不是转字符集编码)传输从而在后台需要解包(php对于encodeURIComponent的应该是自动解包)。

2、对于提交变量没进行安全处理就用来构建SQL查询字符串,很容易被注入攻击。
$init_sql="select branch from xxjsj."+$init_kind+" where region='"+$init_region+"' "; 

一般来说入库处理有两种方式来保证安全,一种是入库前对信息进行转码(这里指的不是字符串语言编码。而是如htmlspecialchars,addslashes或者mysql_real_escape等),出库直接输出;要么是入库只对特殊字符处理(addslashes,mysql_real_escape),出库输出前用htmlspecialchars处理。

3、使用ajax时echo只能使用一次。执行echo之后前台接收到返回值就关闭连接不会继续接受以后的数据了。所以你在 while中执行echo json_encode($response)是错误的,应该先保存所有数据到一个变量然后再输出这个变量:
<?php
$res = array();
while($init_row=@mysql_fetch_array($init_query))
{
  $res[] = iconv('gb2312', 'utf-8', $init_row['branch']); 
  //$res[] = htmlspecialchar(iconv('gb2312', 'utf-8', $init_row['branch']), ENT_QUOTES); 
}
/*
$res数据结构可能如下
array(0=>'a', 1=>'b', 2=>'c' )
*/

if (count($res)) {
  echo json_encode($res);
}
else {
  die;
}
?> 
这儿有个问题:看你源代码写法,DB编码用的是GB2312,那么之前对$init_region,$init_kind处理就应该是转码成GB而不是UTF-8。

前台回调函数如下:
success: function(data) {
  if (data) {
    var str = '';
    for (var i=0, x=data.length; i<x; i++) {
      str += '<option value=' + data[i] + '>' + data[i] + '</option>';
    }
    $("#bg_branch").empty().append(str);
  }
} 

 

注意:我这儿省略了转码过程。如果前后台HTML/JS以及DB都是gb格式,那么在通过ajax传输数据时得对数据进行转码或者编解码(打包解包。一般使用打包方式,因为用JS处理字符集转换很麻烦)。这会多出很大坨代码,并且容易出错。

所以最省事的办法是全站都使用UTF-8编码。

再次提醒:firebug非常适合调试ajax,很多问题一用firebug调试就能发现问题所在。


ps:楼主欠缺的知识点比较多,需要努力。










mark35
mark35
所以项目强制统一使用UTF8可以省很多麻烦事
0
红薯
红薯

首先:提交中文数据建议用 POST 方式,无需进行转码

其次:success: function(data) 这个函数里面,为什么要 decodeURIComponent 呢?无需啊

mark35
mark35
并且表单的POST方式不用转码那也是浏览器(?)自动做编码,后台(比如PHP)在接收到数据后自动解码。这并不代表POST方式不转码。
mark35
mark35
这不是根本解决方式。所谓POST方式不用转码那是因为jquery自己在做转码。
0
qycms_cn
qycms_cn

jquery里的json是狗屎,有很多不完善的地方,对一些返回有特殊符号的,html,js混合的数据支持不好,你查一下从prototype.js的string转换过来的string插件吧。

 

 

/**
 * jquery.string - Prototype string functions for jQuery
 * (c) 2008 David E. Still (http://stilldesigning.com)
 * Original Prototype extensions (c) 2005-2008 Sam Stephenson (http://prototypejs.org)
 */

jQuery.extend({
	__stringPrototype: {
		/**
		 * ScriptFragmet, specialChar, and JSONFilter borrowed from Prototype 1.6.0.2
		 */
	 	JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
		ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
		specialChar: {
			'\b': '\\b',
			'\t': '\\t',
			'\n': '\\n',
			'\f': '\\f',
			'\r': '\\r',
			'\\': '\\\\'
		},
	
		/**
		 * Check if the string is blank (white-space only or empty).
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		blank: function(s) {
			return /^\s*$/.test(this.s(s) || ' ');
		},
		/**
		 * Converts a string separated by dashes into a camelCase equivalent.
		 * For instance, 'foo-bar' would be converted to 'fooBar'.
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		camelize: function(s) {
			var a = this.s(s).split('-'), i;
			s = [a[0]];
			for (i=1; i<a.length; i++){
				s.push(a[i].charAt(0).toUpperCase() + a[i].substring(1));
			}
			s = s.join('');
			return this.r(arguments,0,s);
		},
		/**
		 * Capitalizes the first letter of a string and downcases all the others.
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		capitalize: function(s) {
			s = this.s(s);
			s = s.charAt(0).toUpperCase() + s.substring(1).toLowerCase();
			return this.r(arguments,0,s);
		},
		/**
		 * Replaces every instance of the underscore character ("_") by a dash ("-").
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		dasherize: function(s) {
			s = this.s(s).split('_').join('-');
			return this.r(arguments,0,s);
		},
		/**
		 * Check if the string is empty.
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		empty: function(s) {
			return this.s(s) === '';
		},
		/**
		 * Tests whether the end of a string matches pattern.
		 * @param {Object} pattern
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		endsWith: function(pattern, s) {
			s = this.s(s);
			var d = s.length - pattern.length;
			return d >= 0 && s.lastIndexOf(pattern) === d;
		},
		/**
		 * escapeHTML from Prototype-1.6.0.2 -- If it's good enough for Webkit and IE, it's good enough for Gecko!
		 * Converts HTML special characters to their entity equivalents.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		escapeHTML: function(s) {
			s = this.s(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
			return this.r(arguments,0,s);
		},
		/**
		 * evalJSON from Prototype-1.6.0.2
		 * Evaluates the JSON in the string and returns the resulting object. If the optional sanitize parameter
		 * is set to true, the string is checked for possible malicious attempts and eval is not called if one
		 * is detected.
		 * @param {String} s string to be evaluated
		 * @return {Object} evaluated JSON result
		 */
		evalJSON: function(sanitize, s) {
			s = this.s(s);
			var json = this.unfilterJSON(false, s);
			try {
				if (!sanitize || this.isJSON(json)) { return eval('(' + json + ')'); }
			} catch (e) { }
			throw new SyntaxError('Badly formed JSON string: ' + s);
		},
		/**
		 * evalScripts from Prototype-1.6.0.2
		 * Evaluates the content of any script block present in the string. Returns an array containing
		 * the value returned by each script.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		evalScripts: function(s) {
			var scriptTags = this.extractScripts(this.s(s)), results = [];
			if (scriptTags.length > 0) {
				for (var i = 0; i < scriptTags.length; i++) {
					results.push(eval(scriptTags[i]));
				}
			}
			return results;
		},
		/**
		 * extractScripts from Prototype-1.6.0.2
		 * Extracts the content of any script block present in the string and returns them as an array of strings.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		extractScripts: function(s) {
			var matchAll = new RegExp(this.ScriptFragment, 'img'), matchOne = new RegExp(this.ScriptFragment, 'im'), scriptMatches = this.s(s).match(matchAll) || [], scriptTags = [];
			if (scriptMatches.length > 0) {
				for (var i = 0; i < scriptMatches.length; i++) {
					scriptTags.push(scriptMatches[i].match(matchOne)[1] || '');
				}
			}
			return scriptTags;
		},
		/**
		 * Returns a string with all occurances of pattern replaced by either a regular string
		 * or the returned value of a function.  Calls sub internally.
		 * @param {Object} pattern RegEx pattern or string to replace
		 * @param {Object} replacement string or function to replace matched patterns
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 * @see sub
		 */
		gsub: function(pattern, replacement, s) {
			s = this.s(s);
			if (jQuery.isFunction(replacement)) { s = this.sub(pattern, replacement, -1, s); }
			/* if replacement is not a function, do this the easy way; it's quicker */
			else { s = s.split(pattern).join(replacement); }
			return this.r(arguments,2,s);
		},
		/**
		 * Check if the string contains a substring.
		 * @param {Object} pattern RegEx pattern or string to find
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean result
		 */
		include: function(pattern, s) {
			return this.s(s).indexOf(pattern) > -1;
		},
		/**
		 * Returns a debug-oriented version of the string (i.e. wrapped in single or double quotes,
		 * with backslashes and quotes escaped).
		 * @param {Object} useDoubleQuotes escape double-quotes instead of single-quotes
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		inspect: function(useDoubleQuotes, s) {
			s = this.s(s);
			var escapedString;
			try {
				escapedString = this.sub(/[\x00-\x1f\\]/, function(match) {
					var character = jQuery.__stringPrototype.specialChar[match[0]];
					return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
			    }, -1, s);
			} catch(e) { escapedString = s; }
			s = (useDoubleQuotes) ? '"' + escapedString.replace(/"/g, '\\"') + '"' : "'" + escapedString.replace(/'/g, '\\\'') + "'";
			return this.r(arguments,1,s);
		},
		/**
		 * Treats the string as a Prototype-style Template and fills it with object�s properties.
		 * @param {Object} obj object of values to replace in string
		 * @param {Object} pattern RegEx pattern for template replacement (default matches Ruby-style '#{attribute}')
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		interpolate: function(obj, pattern, s) {
			s = this.s(s);
			if (!pattern) { pattern = /(\#\{\s*(\w+)\s*\})/; }
			var gpattern = new RegExp(pattern.source, "g");
			var matches = s.match(gpattern), i;
			for (i=0; i<matches.length; i++) {
				s = s.replace(matches[i], obj[matches[i].match(pattern)[2]]);
			}
			return this.r(arguments,2,s);
		},
		/**
		 * isJSON from Prototype-1.6.0.2
		 * Check if the string is valid JSON by the use of regular expressions. This security method is called internally.
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean result
		 */
		isJSON: function(s) {
			s = this.s(s);
			if (this.blank(s)) { return false; }
			s = s.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
			return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(s);
		},
		/**
		 * Evaluates replacement for each match of pattern in string and returns the original string.
		 * Calls sub internally.
		 * @param {Object} pattern RegEx pattern or string to replace
		 * @param {Object} replacement string or function to replace matched patterns
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 * @see sub
		 */
		scan: function(pattern, replacement, s) {
			s = this.s(s);
			this.sub(pattern, replacement, -1, s);
			return this.r(arguments,2,s);
		},
		/**
		 * Tests whether the beginning of a string matches pattern.
		 * @param {Object} pattern
		 * @param {String} s string to be evaluated
		 * @return {Boolean} boolean of result
		 */
		startsWith: function(pattern, s) {
			return this.s(s).indexOf(pattern) === 0;
		},
		/**
		 * Trims white space from the beginning and end of a string.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		strip: function(s) {
			s = jQuery.trim(this.s(s));
			return this.r(arguments,0,s);
		},
		/**
		 * Strips a string of anything that looks like an HTML script block.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		stripScripts: function(s) {
			s = this.s(s).replace(new RegExp(this.ScriptFragment, 'img'), '');
			return this.r(arguments,0,s);
		},
		/**
		 * Strips a string of any HTML tags.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		stripTags: function(s) {
			s = this.s(s).replace(/<\/?[^>]+>/gi, '');
			return this.r(arguments,0,s);
		},
		/**
		 * Returns a string with the first count occurances of pattern replaced by either a regular string
		 * or the returned value of a function.
		 * @param {Object} pattern RegEx pattern or string to replace
		 * @param {Object} replacement string or function to replace matched patterns
		 * @param {Integer} count number of (default = 1, -1 replaces all)
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		sub: function(pattern, replacement, count, s) {
			s = this.s(s);
			if (pattern.source && !pattern.global) {
				var patternMods = (pattern.ignoreCase)?"ig":"g";
				patternMods += (pattern.multiline)?"m":"";
				pattern = new RegExp(pattern.source, patternMods);
			}
			var sarray = s.split(pattern), matches = s.match(pattern);
			if (jQuery.browser.msie) {
				if (s.indexOf(matches[0]) == 0) sarray.unshift("");
				if (s.lastIndexOf(matches[matches.length-1]) == s.length - matches[matches.length-1].length) sarray.push("");
			}
			count = (count < 0)?(sarray.length-1):count || 1;
			s = sarray[0];
			for (var i=1; i<sarray.length; i++) {
				if (i <= count) {
					if (jQuery.isFunction(replacement)) {
						s += replacement(matches[i-1] || matches) + sarray[i];
					} else { s += replacement + sarray[i]; }
				} else { s += (matches[i-1] || matches) + sarray[i]; }
			}
			return this.r(arguments,3,s);
		},
		/**
		 * 
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		succ: function(s) {
			s = this.s(s);
			s = s.slice(0, s.length - 1) + String.fromCharCode(s.charCodeAt(s.length - 1) + 1);
			return this.r(arguments,0,s);
		},
		/**
		 * Concatenate count number of copies of s together and return result.
		 * @param {Integer} count Number of times to repeat s
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		times: function(count, s) {
			s = this.s(s);
			var newS = "";
			for (var i=0; i<count; i++) {
				newS += s;
			}
			return this.r(arguments,1,newS);
		},
		/**
		 * Returns a JSON string
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		toJSON: function(s) {
			return this.r(arguments,0,this.inspect(true, this.s(s)));
		},
		/**
		 * Parses a URI-like query string and returns an object composed of parameter/value pairs.
		 * This method is mainly targeted at parsing query strings (hence the default value of '&'
		 * for the seperator argument). For this reason, it does not consider anything that is either
		 * before a question mark (which signals the beginning of a query string) or beyond the hash 
		 * symbol ("#"), and runs decodeURIComponent() on each parameter/value pair.
		 * @param {Object} separator string to separate parameters (default = '&')
		 * @param {Object} s
		 * @return {Object} object
		 */
		toQueryParams: function(separator, s) {
			s = this.s(s);
			var paramsList = s.substring(s.indexOf('?')+1).split('#')[0].split(separator || '&'), params = {}, i, key, value, pair;
			for (i=0; i<paramsList.length; i++) {
				pair = paramsList[i].split('=');
				key = decodeURIComponent(pair[0]);
				value = (pair[1])?decodeURIComponent(pair[1]):undefined;
				if (params[key]) {
					if (typeof params[key] == "string") { params[key] = [params[key]]; }
					params[key].push(value);
				} else { params[key] = value; }
			}
			return params;
		},
		/**
		 * truncate from Prototype-1.6.0.2
		 * Truncates a string to the given length and appends a suffix to it (indicating that it is only an excerpt).
		 * @param {Object} length length of string to truncate to
		 * @param {Object} truncation string to concatenate onto truncated string (default = '...')
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		truncate: function(length, truncation, s) {
			s = this.s(s);
			length = length || 30;
			truncation = (!truncation) ? '...' : truncation;
			s = (s.length > length) ? s.slice(0, length - truncation.length) + truncation : String(s);
			return this.r(arguments,2,s);
		},
		/**
		 * Converts a camelized string into a series of words separated by an underscore ("_").
		 * e.g. $.string('borderBottomWidth').underscore().str = 'border_bottom_width'
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		underscore: function(s) {
			s = this.sub(/[A-Z]/, function(c) { return "_"+c.toLowerCase(); }, -1, this.s(s));
			if (s.charAt(0) == "_") s = s.substring(1);
			return this.r(arguments,0,s);
		},
		/**
		 * unescapeHTML from Prototype-1.6.0.2 -- If it's good enough for Webkit and IE, it's good enough for Gecko!
		 * Strips tags and converts the entity forms of special HTML characters to their normal form.
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		unescapeHTML: function(s) {
			s = this.stripTags(this.s(s)).replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
			return this.r(arguments,0,s);
		},
		/**
		 * unfilterJSON from Prototype-1.6.0.2.
		 * @param {Function} filter
		 * @param {String} s string to be evaluated
		 * @return {Object} .string object (or string if internal)
		 */
		unfilterJSON: function(filter, s) {
			s = this.s(s);
			filter = filter || this.JSONFilter;
			var filtered = s.match(filter);
			s = (filtered !== null)?filtered[1]:s;
			return this.r(arguments,1,jQuery.trim(s));
		},
	
		/**
		 * Sets .str property and returns $.string object.
		 * @param {String} s string to be evaluated
		 */
		r: function(args, size, s) {
			if (args.length > size || this.str === undefined) {
				return s;
			} else {
				this.str = ''+s;
				return this;
			};
		},
		s: function(s) {
			if (s === '' || s) { return s; }
			if (this.str === '' || this.str) { return this.str; }
			return this;
		}
	},
	string: function(str) {
		if (str === String.prototype) { jQuery.extend(String.prototype, jQuery.__stringPrototype); }
		else { return jQuery.extend({ str: str }, jQuery.__stringPrototype); }
	}
});
jQuery.__stringPrototype.parseQuery = jQuery.__stringPrototype.toQueryParams;

 

用法如下:

 

success: function(data){ 
   //json data
   var rs = $.string(data).evalJSON(data);
   // rs 是object           
});
mark35
mark35
狗屎 ? 是你自己后台数据没处理好吧。
0
yanyongshan
yanyongshan
如果返回的是json string,请先用var data=jquery.praseJSON(data)
0
笨蛋EGG
笨蛋EGG
json的问题多数是格式或者字符串拼接时的失误,好好检查一下,用firebug看看返回的都系就知道了····
0
Evo
Evo

引用来自“yanyongshan”的答案

如果返回的是json string,请先用var data=jquery.praseJSON(data)
我就是这么告诉他的,可是楼主不相信我。。
0
n
nmbtzzg
你们的回答都很好,可谁能帮忙改一下代码啊!就这么几行,全当经验交流吗!!!谢谢了!!!
0
Andre.Z
Andre.Z

ajax传输,默认编码是UTF-8,请求的页面如果不是utf-8的,那返回的信息中汉字就会显示乱码。既然已经将汉字编码了,那就无所谓utf-8。

请求页面中数据编码了,那回调函数中,就需要解码,decodeURIComponent是需要的。

这里,ajax获取的,是请求页面的responseText ,是作为字符串来的。var s_data=decodeURIComponent(data); 这里s_data是字符串形式的,不是对象,那么你后面的所有操作都是无效的。可以用eval,也可以用jquery.praseJSON之类的,将返回的字符串转换为对象,那么,才有意义。

 success: function(data){document.write(data);}你看看输出是什么,然后,贴出来大家看看。

ajax发送请求去页面时,你是get方式,那么,要注意构造的请求字串中,汉字的表现形式。可以监控下页面的请求,看发送的数据对不对,发送的数据编码有问题,你目标页面解析当然也不对了。可以用httpwatch之类的监控检测下看看。

首先,要保证传输的数据和返回的数据正确,再保证对于返回信息的解析没问题,你才能看到效果。

并不是jquery怎么怎么D,它只是将ajax的一些东西进行了封装而已。封装的东西再怎么也变不到哪里去。从底层的检测做,就不会有问题。

0
mark35
mark35

楼主你后台PHP文件本身编码是什么?

数据库编码是什么?

前台HTML/JS编码是什么?

楼主你用firebug看看后台返回的数据是什么?

0
张攀
张攀
调试下看看  不就知道问题在哪了吗?
返回顶部
顶部