1、问题描述 这周搬砖的时候,前端经过ajax获取后端的数据后,照例用 对象.属性
的方式取值,然而结果老是老是不能如预期般展现在页面上。 先写个 demo 还原下场景:选中一个下拉框列表选项后,会在下拉框下面展现文字。 这是下拉框的html部分:javascript
<html> <head> <title>JSON DEMO</title> <meta charset="UTF-8"> </head> <body> <select id="device"> <option value="">终端设备</option> <option value="1">PC Web</option> <!-- <option>...</option> --> </select> <div id="tip"></div> </body> </html>
PHP代码以下:用来返回数据(接收、处理过程略)php
<?php $onLines = [ 1 => 'PC Web', 2 => 'iPad HD', 5 => 'Touch' ]; echo json_encode(['data' => $onLines]);
JS代码以下:html
<script type="text/javascript"> $("#device").change(function() { var selectVal = $("#device").val(); if (selectVal == '') { $("#tip").html(''); return; } # code... ajax 部分的代码见下 }); </script>
ajax 部分的代码用来接收从后端(PHP)传过来的数据,并处理。前端
$.ajax({ url: 'device.php', type: 'post', dateType: 'json', data: { device: selectVal }, success: function(result) { var onlineDevices = result.data; var onlineTip = '容许' + onlineDevices[selectVal] + '类型的2台设备同时在线。'; $("#tip").html(''); $("#tip").append(onlineTip); } });
使用 console.log
在控制台输出结果,以下图所示,能够看到后端返回的数据是没有问题的, 再使用 typeof
查看返回的数据类型,前端收到的数据是JSON字符串!而不是JSON对象!java
success: function(result) { console.log(result); console.log(result.data); console.log(typeof result); }
2、解决方法 找到问题就好办了,只须要把 json 字符串转成 json 对象就行了,最简单的办法是 JSON.parse()
。ajax
success: function(result) { var onlineDevices = JSON.parse(result).data; # code ... }
3、总结 一、json字符串和json对象的区别json
// JSON 字符串 var str1 = '{"data":{"1":"PC Web","2":"iPad HD","5":"Touch"}}'; // JSON 对象 var str2 = {"data":{"1":"PC Web","2":"iPad HD","5":"Touch"}}; console.log(str1); console.log(typeof str1); console.log(str2); console.log(typeof str2);
能够看到json字符串和json对象的形式很像,但前者比后者多了一对引号,其内容包含在引号里了。调试台的结果以下: 后端
二、json字符串转为json对象的方法 后端数组
-
设置header头中的内容类型,将 Content-Type 设置为 text/json。
header('Content-Type:text/json;charset=utf-8');
注:前端直接处理便可,不须要 JSON.parse() 处理。 但项目中用的是框架,全部的PHP文件(业务层)均没有显式设置 header,虽然在demo中此方法有效,可依然不明白为何别的地方返回的是json对象,而这里返回的倒是json字符串了。app -
强制类型转换(object) 此方法无效! 若是将一个对象转换成对象,它将不会有任何变化。若是其它任何类型的值被转换成对象,内置标准类 stdClass 的一个实例将被创建。 以上面的数组为例,强制类型转换的结果以下:
var_dump((object)['data' => $onLines]); // 结果以下: object(stdClass)#1 (1) { ["data"]=> array(3) { [1]=> string(6) "PC Web" [2]=> string(7) "iPad HD" [5]=> string(5) "Touch" } }
而json_encode((object)['data' => $onLines]);
获得的仍是json字符串。
前端
- var obj = JSON.parse(str); JSON.parse()方法,必须保证传入的是json字符串,若是是json对象会报错。
- var obj = jQuery.parseJSON(str); parseJSON()方法是jQuery方法,仅支持标准json格式,不然会报错。 下面这些是无效的 JSON 字符串:
"{test: 1}" //test是属性名称,必须加双引号 "{'test': 1}" //test是属性名称,必须用双引号(不能用单引号) "'test'" //test是属性名称,必须用双引号(不能用单引号) "undefined" //undefined 不能表示一个 JSON 字符串; null能够 "NaN" //NaN 不能表示一个 JSON 字符串; 用Infinity直接表示无限也是不容许的
- var obj = eval('(' + str + ')'); eval()方法是js方法,也是必须保证传入的是json字符串,不然会报错。
4、疑惑 查了一下PHP的 json_encode()函数,PHP手册给出的结论是成功时返回字符串。 Return Values Returns a JSON encoded string on success or FALSE on failure.
既然json_encode()函数返回的是字符串,为何在项目中其余地方能够直接使用 对象.属性
的方式呢?
后记 更新于2019-02-25 今天不死心,又研究了一下,还问了一个朋友,对方提醒估计大几率是编码和头的设置有问题,而后我逐行查代码,发现 ajax 部分的dataType
我写成了dateType
,一字之差~ 噢,天啊,太丢人了!之后绝对不能再犯这么二的错误了!