PHP操作JSON


第19 章PHP 操作 JSON 1 第19章PHP 操作 JSON 本章主要 内容包括: � JSON 的数据格式 � JSON 的数据类型 � 使用 PHP进行 JSON 解码 � JavaScript 解析 JSON � JSON 与XML进行比较 � 使用 PHP进行 JSON 编码 � 将MySQL 数据转换为 JSON � 自动完成的应用 本章全面 介绍 JSON(JavaScriptObjectNotation)是一种轻 量级的数据交换 格 式,其基 于 JavaScript语法,是 StandardECMA-262的一个子 集。 JSON格式非常 有利于阅读和编 写,笔者认为最 好的一个特性就 是在浏览器中不 需要安 装任何插 件或 ActiveX。只要浏 览器支持 JavaScript脚本语言 ,就可以 顺序进行 JSON 的 解析。 本 章主要 介绍 使用 PHP操作JSON, 以及使 用 JavaScript来 处理 JSON请 求和 响应内容 。 19.1 为什么要使用 JSON 使用 JSON方便在前 台操作 ,因为许多 技术在各浏览器 中都存在兼容性 的问题 。其中包 括CSS、JavaScript、DOM、XML和XSLT。特别是 XML和XSLT还需要创 建对象进行操 作,而各浏览 器又提供不一样 的操作对象 。所以要使 用一种技术在各 浏览器上兼容 ,而基 于 JavaScript的JSON是完全独立于语言的文本格式。一般情况下只要浏览器支持 JavaScript就可以操 作 JSON。 � 多语言支 持 目前 ,几乎所有 的流行编程语言 都支持 JSON 格式 ,其中包括 C、C++、C#、Delphi、 Java、JavaScript、PHP、Python、Perl、Ruby、Tcl等等,甚 至还有许多叫不 上名 字的语言 。 � 灵活性 使用 JSON可以使操 作更加灵活方便 。尤其是在 多个列表的情况 下 ,不像数组 需要遍历 整个数组 找到相对的值 ,而JSON只需要引 用对象的名称就 可以得到对应的 值 ,使用起来 非 常方便, 灵活。 19.1.1 JSON 与XML 比较 JSON的 横空 出世 让 许多 Web开 发者 冷漠 了 XML, 因为 JSON凭 借与 XML相 媲美 的优 越扩 展性 ,在 可读性 方面 JSON是使 用 JavaScript脚本 语言 的语 法规范 。在 编解 码方 面 JSON格式存在 着先天性的优势 ,可以 说JSON格式更适 合用来开发基 于Ajax的Web程序 , 因为其编 解码难度几乎为 0,也可以说 是根本没有难度 。下面举例 对比一下 XML和JSON格 式,代码 如下: 2 Haley Wang 1581094**** whloko@gmail.com WenYun Chen 1591396**** yunyun@hotmail.com Yang Liu 1310726**** liuyang@yahoo.com 下面使用 JSON来表示同 样的数据,格式 如下: [ { "name":"Haley Wang", "phone":"1581094****", "email":"whloko@gmail.com" }, { "name":"WenYun Chen", "phone":"1591396****", "email":"yunyun@hotmail.com" }, { "name":"Yang Liu", "phone":"1310726****", "email":"liuyang@yahoo.com" } ] 不言而喻 , JSON的格式更 加简洁。下面介 绍一下 JSON的数据格 式。 第19 章PHP 操作 JSON 3 19.2 JSON 数据格式和语法 JSON 的数据格 式被大多数计算 机语言所支持, 从而使其实现跨 语言成为一种可 能。如 果读 者比 较了 解 JavaScript 语言 ,那 么使 用 JSON 会更 加简 单, 容易上 手。 下面 来介 绍 JSON 的数据组 织结构,以及一 些其所支持的类 型。 19.2.1 JSON 数据结构 JSON 支持两种 数据结构,分别 为对象和数组。 对象可以 表示为无序的键 /值对集合 ,在Python 中被称为 字典 ,在PHP 中称为关 联索 引 数组, 在其 他语 言中也 被称 为哈 希表。 一个 对象 以 { 左 大括号 开始 ,并 以 } 右 大括号 结束,键 与值之间使用冒 号( :)分隔; 键 /值对之间 使用逗号( ,)分隔。 例如: {"Author":"Haley Wang", "Version":"1.0.0.2" } 数组被 称为值的有序列 表,在其他语言 中一般也都会被 称为数组。一个 数组使用 [ 左 方括号开 始,并以 ] 右方括号 结束,值与值之 间使用逗号( ,)分隔。 例如: ["Haley Wang", "1.0.0.2" ] 在对象的 值中可以嵌套数 据 ,并且在数 组的值中也可以 嵌套对象 ,本节以下 将介绍的数 据类型都 可以用在这两种 结构上。这也是 JSON 的灵活性 之一。 19.2.2 JSON 数据类型 JSON 数据的值支持6种数据类型,分别为string、number、object、array、 boolean(true 和false)和 null。 string 类型与大 多数语言用法相 同,下表 19-1 列出 string 类型的转 换字符。 表19-1 JSON 格式中 string 的转换字符 字面量 含义 \" 表示一个双引号。 \/ 表示一个斜线分隔符。 \\ 表示一个反斜线。 \b 表示一个空格。 \f 表示一个换页符。 \n 表示一个换行符。 \r 表示一个回车符。 \t 表示一个制表符。 \uXXXX 表示任何 Unicode 字符, XXXX 为四个十六进制代码。 number 类型也与 大多数语言类似 ,还可以使 用科学计数法 ;但未使用 八进制和十六进 制编码。 4 19.3 PHP 中的 JSON PHP从5.2版本开始 内置了 JSON的支持。 本节将介绍 PHP内置的两 个函数,分别 为 json_encode和json_decode函数 ,如同对象 的序列化一样 ,一个为编 码函数 ,另一个 为解码函 数。 � json_encode()函数 语法如下 : string json_encode (mixed value ) json_encode()函数的用于将value转换为JSON格式的字符串。待编码参数 value除了 resource类型之外 ,可以为任何数 据类型。示例如 下: //源文件位置:光盘 :\chapter19\ json_encode.php " 王小明 ", "age"=>19, "studentID"=>"30108", "contact"=> array( "phone"=>"1582088XXXX", "email"=>"xiaoming@gmail.com", "address"=>"XX 市XX区XX街XX号" )); $json_string =json_encode( $student ); echo $json_string; ?> 执行结果 将输出如下格式 的 JSON字符串。 { "name":"\u738b\u5c0f\u660e", "age":19, "studentID":"30108", "contact": { "phone":"1582088XXXX", "email":"xiaoming@gmail.com", "address":"XX\u5e02XX\u533aXX\u8857XX\u53f7" } } 注意 ,该函数只 接受 UTF-8的编码数 据 。在非 UTF-8编码的情 况下 ,中文字符 编码将 得到空白 字符 。最好将 php页面文件 保存为 UTF-8格式 ,这样就可 以正常进行编码 ;也可 第19 章PHP 操作 JSON 5 以使用 iconv或者 mb函数将中 文字符转为 UTF-8的格式, 然后在进行编码 。 � json_decode函数 语法如下 : mixed json_decode( string json [,bool assoc] ) json_decode()函数用 于将一个 JSON格式的 字符串转换为 PHP的变量 。 json参数 为待解码 的字符串 。如果 可选参数 assoc 为TRUE时,将返回一 个数组 ;否则返回 一个对象 。 缺省为 FALSE。 例如 ,我们运用 Ajax技术 ,从客户端 发送一个 JSON格式字符 串到服务器端 ,然后服 务 器的 PHP文 件将 JSON字 符串 解码 成一 个 数组 ,再 返回 给 客户 端显 示。 在 实际 应用 中一 般将 JSON直接和解 码后存储起来 ,这里的应 用过程虽然意义 不大 ,只是为了 读者一个最好 的演示效 果。 1.1.1.1.服务器 端代码 //源文件位置:光盘 :\chapter19\ json_decode.php 以上代码 使用 file("php://input")来获取客 户端请求的数据 ,并返回一 个数组 。 然后使用 implode()函数连接 数组中的所有元 素。最后将解码 后数组打印出来 。 2.2.2.2.客户端 代码 //源文件位置:光盘 :\chapter19\ json_decode.htm json_decode
执行输出 结果如图 19-1 所示。 第19 章PHP 操作 JSON 7 图19-1 json_decode()函数解码 JSON数据 19.4 从MySQL 数据库到 JSON 上面介绍 的 json_encode()函数虽然 可以将许多种数 据类型转换成 JSON格式 ,但是 对于资源类型就无能为力了。MySQL 使用的就是资源类型,下面修改第16 章中介绍的 Haley_Data类, 使其 可以 将数据 集转 换成 JSON格式 。在 原有 的 Haley_Data 类中 添加 如 下代码。 //源文件位置:光盘 :\chapter19\ Haley_Data.php public function GetArray() { if($this->resultSet) { $resultSetArray =array("ResultSet" => array()); $this->resultSet->data_seek(0); while( $rowSet =$this->resultSet->fetch_array(MYSQLI_ASSOC) ) { array_push($resultSetArray["ResultSet"], $rowSet); } return $resultSetArray; } } public function GetJOSN() { 8 return json_encode( $this->GetArray() ); } 以上 代码既 可以从 MySQL中获 取数组 类型,又 可以获 取 JSON格式 的字符 串。首先 将 MySQL数 据集转 换成 数组 ,因为 json_encode()函 数可以 接受 数组 类型, 所有 非常 容易 就可以将 数组类型转换为 JSON格式字符 串。 下面使用 修改过的 Haley_Data类从 student 数据库的 list 表中提取 数据集,并转换 为 JSON格式的字 符串输出显示, 示例如下。 //源文件位置:光盘 :\chapter19\ databaseToJson.php Query( $queryString ); echo $haley_data->GetJOSN(); ?> 执行输出 结果如图 19-2 所示。 图19-2 使用 Haley_Data 类将数据集转换为 JSON 19.5 使用 JavaScript 转换 JSON 使用 JavaScript 来转 换 JSON非常 简单 ,使 用 eval()函数 就可 以完 成转换 。下 面我 们 根据 JSON官方 (http://www.json.orgRFC4627)提供的文 档完成转换,代 码如下 : //源文件位置:光盘 :\chapter19\ Haley.js String.prototype.toJSON =function() { var str =this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); try{ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str) && !(/^\s*$/.test(str)) ?eval('(' +this +')') :null; }catch(e){ 第19 章PHP 操作 JSON 9 throw new String("Syntax Error: Badly formed JSON string!"); } } 以上代码使用的prototype原型为JavaScript添加一个原型函数,也添加了对 JSON格式的验 证功能。然后将 JSON转换对应 的对象返回。 下面 使用 toJSON()原型 函数 将一 个 JSON字符 串转换 为对应的 JavaScript对象 , 代码如下 。 //源文件位置:光盘 :\chapter19\toJson .htm var jsonString ='{"people":[ {"name":"FuYang"}, {"name":"TanWang"}, {"name":"YanLiu"}]}'; var jsonObject =jsonString.toJSON(); document.write ln (jsonObject.people[0].name); //或者另一种写法 document.writeln(jsonObject['people'][0]['name']); document.writeln("
"); //使用 for...in... 循环结构显示 for(jsonItem in jsonObject.people) { document.write(jsonObject.people[jsonItem].name +' '); } 执行输出 结果如图 19-2所示。 图19-2 使用 toJSON原型函数 19.6 实例:利用 JSON 实现自动完成 自动完成 功能是一种增强 用户体验 ,方便用户 输入的成熟解决 方案 。可以从许 多知名网 站 看到其 效果 ,例 如, www.google.cn 等 。下面 我们 使用 JSON和Ajax技 术来实 现基 本的 自动完成 功能。 10 19.6.1 数据 库设计 首 页创 建一 个 autocomplete数 据库 ,然 后 使用 mysql命 令导 入下 面 路径 的备 份文 件或者创 建 citys表,创建 语句如下。 //数据库备份文件位置:光盘 :\chapter19\ AutoComplete\data\autocomplete.sql CREATE TABLE `citys` ( `uid` int(10) unsigned NOT NULL auto_increment, `name` varchar(255) default NULL, `spell` varchar(255) NOT NULL, PRIMARY KEY (`uid`) )ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 19.6.2 服务 器端代 码 在服务器 实现一个 AutoComplete类,用于对关 键字进行查询 。然后使用 实例化该类 , 并通 Haley_Data类完成 JSON的输出。 具体代码如下: //源文件位置:光盘 :\chapter19\ AutoComplete \autocomplete.php getJSON(); } //定义 AutoComplete 类,查询指定的关键字数据集,并将数据集转换为 JSON 格式显示。 class AutoComplete { private $haley_data; private $keyword; public function __construct($keyword ='', $dataKey ='autocomplete') { 第19 章PHP 操作 JSON 11 $this->keyword =$keyword; $this->haley_data =new Haley_Data($dataKey); } public function getJSON() { $patterns =array('/\s+/', '/"+/', '/%+/'); $replace =array(''); $this->keyword =preg_replace($patterns, $replace, $this->keyword); $queryString ="SELECT spell, name FROM citys WHERE spell LIKE '{$this->keyword}%' ORDER BYspell"; $this->haley_data->Query( $queryString ); return $this->haley_data->GetJOSN(); } } ?> 以上 PHP代码 实现 了将 接收到 的关 键字 ,然后 在数 据库 中查询 该关 键字 。接着 返回 查 询数据集 的 JSON格式。 19.6.3 自动 完成类 设计 自动完成 类使用了 Haley.js文件和 Haley.Ajax框架 ,Haley.js文件已经 在本章 前 面介绍 过, 用来 将 JSON字 符串转 换成 JavaScript对 象。 Haley.AutoComplete类 只 实现 了基 本 的自 动完 成类 , 不包 含键 盘选 择 等功 能; 主要 目 的是 为了 介绍 从 服务 器获 取 JSON数据,并 将其显示出来的 转换过程。 具体代码 如下: //源文件位置:光盘 :\chapter19\ AutoComplete \js\ Haley.AutoComplete.js if(!Haley) var Haley ={}; Haley.AutoComplete =function() { this.construct.apply(this, arguments); } Haley.AutoComplete.prototype = { /* *Autocomplete 类的构造函数,接收一个选项对象。 */ construct: function(options) { var instance =this; 12 this.options =options || {}; //定义文本框控件的存储对象。 this.eKeyword =this.options.eKeyword; //定义显示关键字的提示框对象。 this.eSuggest =this.options.eSuggest; //定义显示关键字的条目,不指定或指定为 0则不加条目限制。 this.limit =this.options.limit || 0; //定义一个关键字缓存对象。 this.keywordCache =new Object(); this.keywordPointer =null; this.keywordTrack =null; this.controlCheck =null; //定义一个 Ajax 请求对象。 this.haleyAjax =new Haley.Ajax(this.options.ajaxOptions || { method: "post", timeout: 10, async: true, url: this.options.url}); this.eKeyword.onfocus =function(){ instance.start();}; this.eKeyword.onblur =function() {clearInterval(instance.controlCheck)}; }, /* *开始检测用户输入,调整数据缓存对象。 */ start:function() { var instance =this; this.controlCheck =setInterval( function(){instance.checkKey();}, 200); }, /* *获取用户输入内容,该方法会被定时调用。 *在该方法中判断什么时候向服务器获取数据,什么时候从数据缓存中获取。 */ checkKey: function() { var keyword =this.eKeyword.value; 第19 章PHP 操作 JSON 13 this.keywordPointer =keyword ?keyword.charAt(0).toUpperCase() :''; if(keyword == "") { this.closeSuggest(); } else if(!this.keywordCache[this.keywordPointer] && this.keywordTrack != keyword) { this.getKeywordList(keyword); } else { this.keywordTrack =keyword; this.openSuggest(); } }, /* *用于通过 Ajax 获取关键字列表,如果获取成功,则将列表存入 keywordCache 缓存中。 *如果没有查询到关键字列表,则在指定属性存入一个空列表。 */ getKeywordList: function(keyword) { var instance =this; this.haleyAjax.onComplete =function(responseObject) { var json =responseObject.textString.toJSON(); if(json &&json.ResultSet &&json.ResultSet.length >0) instance.keyword Cache [instance.keywordPointer] = json.ResultSet; else instance.keyword Cache [instance.keywordPointer] =[]; } this.keywordTrack =keyword; this.haleyAjax.start({"keyword": this.keywordPointer}); }, /* *关闭提示框 */ closeSuggest: function() 14 { this.eSuggest.style.visibility ='hidden'; this.keywordTrack =""; }, /* *打开提示框,生成指定条目的关键字列表。 */ openSuggest: function() { this.eSuggest.style.visibility ='visible'; this.eSuggest.innerHTML =""; for(attrib in this.keywordCache[this.keywordPointer]) { var spell =this.keywordCache[this.keywordPointer] [attrib].spell; var items =this.eSuggest.childNodes.length; if( this.limit != 0&&items >this.limit ) break; else if( spell.indexOf(this.keywordTrack) == 0) { var name =this.keywordCache[this.keywordPointer] [attrib].name; this.eSuggest.innerHTML += "
" +name +"" +spell +"
"; } } } } 自动完成 中几乎所有的技 术难点都体会在 AutoComplete类中 。因为其负 责整合数据 资源,完 成关键字的显示 。 在AutoComplete类中 ,运用了数 据缓存机制 。当用户输 入一个单词或者 一个字母时 , 会将用户 输入内容的第一 个字母取出 。首先判断 数据缓存对象中 是否含有该字母 属性 ,如果 含有则就 地取出 ;如果不包 含该字母属性 ,则将该字 母作为关键字请 求查询 。如果服务 器查 询到相应 的关键字的数据 集 ,则将数据 集转换为 JSON格式的字 符串响应给客户 端 。当客户 端接收到 JSON 格式字符 串 ,将其转换 为对象 ,然后获取 其中的关键字列 表 ,再以查询 字母 作为属性 存入数据缓存对 象。数据缓存( KeywordCache)机制如 图 19-3 所示。 第19 章PHP 操作 JSON 15 图19-3 AutoComplete类的 KeywordCache 机制 数据是以 数组方式存入 KeywordCache 的各属性 中 ,例如 [A]表示 KeywordCache 的A 属性,也 就是所有以 A开头的关 键字的列表。其 中有两种引用方 式,如下: KeywordCache['A'] = [keyword_list, ...] KeywordCache.A = [keyword_list, ...] 各 关键字 列表 的长 度不同 ,其 中有 一种特 殊的 空列 表。例 如图 19-2 中 的属性 N, 这个空 列 表用来 表示 没有 查询到 任何 以字 母 N开 头的关 键字 ;如 果下次 用户 再次 输入以 字母 N开 头的关键 字 ,系统将从 KeywordCache 中检索 ,发现属性 为 N的空列表 后将不提供任何 显 示。 19.6.4 客户端完成 有了AutoComplete 类和Haley_Ajax 框 架协 同 工 作, 一 切将 变 得 更加 简 单。 在 客 户端页面 上需要获取输入 关键字文本框的 对象和显示提示 信息元素的对象 ,将其以对 象的形 式 传给 AutoComplete 类 的构造 方法 。还 有一个 必选 就是 指定 该AutoComplete 对 象的 查询数据 的 url,limit 为一个可 选项,用来限制 提示信息的条目 。 页面中 还有关于 CSS 的定义 ,用于定义字体 、文本框和提示 框的样式。此 CSS 的定义 将非常重 要,忽视相关定 义显示结果可能 会一团糟。具体 代码如下: // 源文件位置:光盘 :\chapter19\AutoComplete\autocomplete.htm AutoComplete
假如输入 wu进行查询 ,自动完成的显 示效果如图 19-4 所示。 第19 章PHP 操作 JSON 17 图19-4 输入 wu后自动完成效果 几乎所有 的异步应用都需 要处理传输数据 。如果Ajax采用JSON作为数据 的传输格式 , 那么 使 JavaScript拥有 处理复杂 数据类 型的能力 。同时 给客户端 的解析 带来方便 、简单 的特性, 并有效降低了宽 带的占用率。
还剩16页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 6 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

whloko

贡献于2015-01-18

下载需要 6 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf