女朋友不会 JSON 怎么办?

目录
[隐藏]

某天,女朋友问我关于 JSON 的问题,虽然心里清楚,但却表述不清,她不理解,这有说明自己对 JSON 还没有透彻的理解,于是就有了这篇文章。

虽然 JSON 都知道了,但不妨再介绍一下。

1、JSON 简介

JSON ,全称是 JavaScript Object Notation,即 JavaScrip 对象标记法。这是一种轻量级(Light-Weight)、基于文本的(Text-Based)、可读的(Human-Readable)格式。

1.1 JSON 的语法规则

  1. 数组(Array)用方括号(“[]”)表示。
  2. 对象(Object)用大括号(”{}”)表示。
  3. 名称/值对(name/value)之间用冒号(”:”)隔开。
  4. 名称(name)置于双引号中,值(value)有字符串、数值、布尔值、null、对象和数组。
  5. 并列的数据之间用逗号(“,”)分隔
  6. 数组或对象的每个成员的值,可以是简单值,也可以是复合值

2、JSON 在 JavaScript 和 PHP 中

首先弄清楚的一点是 JSON 的表示

在 JavaScript 中 JSON 有如下表示形式:

var jsonArr = [{"name":"lucy","age":18},{"name":"lala","age":17}];   // JSON 数组

var jsonObj = {"name":"lucy","age":18};   // JSON 对象

var jsonStr = '{"name":"lucy","age":18}';  // 符合 JSON 格式的字符串

在 PHP 中 JSON 就只有如下表示了:

$jsonStr = '{"name":"lucy","age":18}';   // 符合 JSON 格式的字符串

之所以由上述差异,最大原因还是因为 JavaScript 支持 对象/数组 字面量,而 PHP 不支持。

所以说,从 PHP 返回 JSON数据到前端,实际上就是返回符合 JSON 格式的字符串!
下面以 ajax 请求 JSON 数据为例说一下。

假定有 index3.php ,向前端返回 JSON 字符串,如下图:

假定有 index4.html 向 index3.php 发 ajax 请求,如下图。

显然 js 中得到的只是符合 JSON 格式的字符串,所以无法通过 data.a 以对象的形式访问。

这就要提到 JSON 字符串转 JSON 对象了。

2.1 JSON 字符串转 JSON 对象

常见的转化方式有三种:

obj = $.parseJSON(data);

obj = eval('('+data+')');

obj = JSON.parse(data);

看下转化后的结果:

可以看到,已经成功将 JSON 字符串转化成 JSON 对象了。其它两者是一样的,就不上图了。

2.2 推荐用 JSON.parse()

上面给出了三种方式,但推荐使用的只有 JSON.parse() ,其它两者都或多或少有些问题。

2.2.1 eval()

JavaScript 原生的 eval() 的原意是:eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码

但这里却用 eval('('+data+')') 来实现对象化。

为什么要 eval这里要添加('('+user+')') ”呢?

原因在于:eval本身的问题。 由于json是以”{}”的方式来开始以及结束的,在JS中,它会被当成一个语句块来处理,所以必须强制性的将它转换成一种表达式。

加上圆括号的目的是迫使eval函数在处理JavaScript代码的时候强制将括号内的表达式(expression)转化为对象,而不是作为语句(statement)来执行。举一个例子,例如对象字面量{},如若不加外层的括号,那么eval会将大括号识别为JavaScript代码块的开始和结束标记,那么{}将会被认为是执行了一句空语句。所以下面两个执行结果是不同的:

alert(eval("{}"); // return undefined

alert(eval("({})");// return object[Object]

上述这个答案是网上流传很广的,但由于自己的 JS 基础还不扎实,所以也还是不理解为什么可以通过 eval 实现对象化。(如有大牛路过,烦请解答一下,万分感谢)。

谈到 eval ,第一个念头就是最好不要使用,为什么呢?可以参考这篇文章:https://www.zhihu.com/question/20591877

eval 函数的描述可以参考 MDN 的文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval

2.2.2 Function 对象进行转化

在原生 JS 中还可以通过 Function 对象将 JSON 字符串转化成 JSON 对象( JavaScript 实在是博大精深 )

var json='{"name":"CJ","age":18}'

data =(new Function("","return "+json))();

这个方法实际中用的很少,最典型的应用是在 jQuery的 ajax 方法的 success 下实现对返回数据 data 的解析。参考自:https://www.cnblogs.com/chenguangliang/p/6688730.html

2.2.3 $.parseJSON()

该方法是 jQuery 中,不过从 jQuery 3.0 开始,就不再推荐使用了。用该方法转化也会存在一些问题,具体可参考 jQuery.parseJSON() 文档说明:http://www.css88.com/jqapi-1.9/jQuery.parseJSON/

2.2.4 JSON.parse()

JSON.parse() 是推荐使用的,详细内容也请参考 MDN 文档:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON

2.3 其实可以不用转换

在请求后端的一个 json 字符串时,可以通过在请求中指定 MIME 类型来直接得到 JSON 对象。在 jQuery 提供的 ajax 方法中通过设置 dataType 属性为 'json' 即可,如下图:

请求头如下:

当然,jQuery 提供了一个获取 json 数据更便捷的方法:$.getJSON()

关于这个方法的细节参考 jQuery API 文档吧:http://www.css88.com/jqapi-1.9/category/ajax/shorthand-methods/

3、PHP 中 json_encode 和 json_decode

通俗的讲:

json_encode 就是将 PHP 中的 对象/数组 序列化成符合 json 格式的字符串。
json_decode 就是将符合 json 格式的字符串反序列化成 对象/数组。

官方手册上详细说明参考:

json_encode:http://php.net/manual/zh/function.json-encode.php

json_decode:http://php.net/manual/zh/function.json-decode.php

这里要提一点,PHP 中的对象通常都是有类对应的,而通过 json_decode 从 标量(json 字符串) 中反序列化形成的对象,通常没有类与之对应,此时,PHP 中会有一个称为“stdClass”的类会收留该对象!

如下图:

反序列化成数组,只需要给 json_decode 添加第二个参数为 true 即可。

在 PHP 中使用 json 需要注意一点:由于 JSON 只接受 utf-8 编码的字符,所以 json_encode() 的参数必须是 utf-8 编码,否则会得到空字符或者null。当中文使用 GB2312 编码,或者外文使用 ISO-8859-1 编码时,需要特别注意!

编码问题可以参考我的另一篇博文:编码简述

4、JavaScript 中对象和数组

JS中,集合既可以用 数组 表示也可以用 对象 表示。但数组表示有序数据的集合,而对象表示无序数据的集合。如果数据的顺序很重要,就用数组,否则就用对象。

而 JS 中的关联数组其实就是对象,对象其实就是关联数组!

这和 PHP 中的是不一样的,PHP 中 索引数组 和 关联数组 都是数组。

这两点认识来自阮一峰的两篇博文:

在 PHP 中使用 JSON

数据类型和 JSON 格式

5、总结

JSON 使用并不难,主要还是理解好表示的形式,在前后端交互时关键是理清到底接受到的是什么样的数据(字符串还是对象)。当然,本文并没有牵涉到 跨域 的问题,或许有机会再写。
给女朋友解决了问题,自己也理解更加透彻了,甚好甚好。

JavaScript 博大精深,要学好基础都还有漫漫长路要走,但幸运的是一直在路上。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

To