zoukankan      html  css  js  c++  java
  • PHP的json_encode()函数与JSON对象

    一、问题描述
    这周搬砖的时候,前端通过ajax获取后端的数据后,照例用 对象.属性 的方式取值,然而结果总是总是不能如预期般展示在页面上。
    先写个 demo 还原下场景:选中一个下拉框列表选项后,会在下拉框下面展示文字。
    这是下拉框的html部分:

    <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
    $onLines = [
    	1 => 'PC Web',
    	2 => 'iPad HD',
    	5 => 'Touch'
    ];
    echo json_encode(['data' => $onLines]);
    

    JS代码如下:

    <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对象!

    success: function(result) {
    	console.log(result);
    	console.log(result.data);
    	console.log(typeof result);
    }
    
    

    查看后端返回数据

    二、解决方法
    找到问题就好办了,只需要把 json 字符串转成 json 对象就好了,最简单的办法是 JSON.parse()

    success: function(result) {
        var onlineDevices = JSON.parse(result).data;
        # code ...
    }
    

    三、总结
    1、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对象的区别

    2、json字符串转为json对象的方法
    后端

    • 设置header头中的内容类型,将 Content-Type 设置为 text/json。
      header('Content-Type:text/json;charset=utf-8');
      注:前端直接处理即可,不需要 JSON.parse() 处理。
      但项目中用的是框架,所有的PHP文件(业务层)均没有显式设置 header,虽然在demo中此方法有效,可依然不明白为什么别的地方返回的是json对象,而这里返回的却是json字符串了。

    • 强制类型转换(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字符串,否则会报错。

    四、疑惑
    查了一下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,一字之差~
    噢,天啊,太丢人了!以后绝对不能再犯这么的错误了!

  • 相关阅读:
    [ZOJ 4062][2018ICPC青岛站][Plants vs. Zombies]
    [Wannafly挑战赛28][B msc和mcc][预处理+枚举]
    [codeforces Mail.Ru Cup 2018 Round 1 D][ xor 操作]
    [codeforces round#475 div2 ][C Alternating Sum ]
    [zoj4045][思维+dfs]
    [zoj4046][树状数组求逆序(强化版)]
    费马大定理以及求解a^2+b^2=c^2的奇偶数列法则
    【HDOJ3567】【预处理bfs+映射+康拓展开hash】
    POJ1279 Art Gallery 多边形的核
    第八周 Leetcode 44. Wildcard Matching 水题 (HARD)
  • 原文地址:https://www.cnblogs.com/sunshineliulu/p/10422677.html
Copyright © 2011-2022 走看看