您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息
三六零分类信息网 > 沧州分类信息网,免费分类信息发布

JSON Eval Trick in PHP_PHP教程

2026/6/5 14:53:44发布7次查看
php从5.2版本开始提供json_encode()和json_decode()函数,分别用于json的序例化和反序列化。不幸的是,现在仍然有许多主机运行着php5.2之前的版本,所以就不得不自己动手写json解析了。
json encodejson的编码并没有什么难度,要点就两个:
对object、array中的元素进行递归遍历,注意要将关联数组转换成json中的object literal。对字符串内容中引号、换行符等特殊字符进行转义,并将非ascii字符转换成unicode转义序列的形式。下面是json编码方法的实现:
/** * json encode * @warn any input string must be utf-8 encoding * @param {any} $data any type object to serialize. * @return {string} serialized json string. */function json_stringify($data) { if (is_null($data)) return 'null'; if (is_scalar($data)) return json_stringify_scalar($data); if (empty($data)) return '[]'; if (is_object($data)) { $data=get_object_vars($data); if (empty($data)) return '{}'; } $keys=array_keys($data); if ($keys===array_keys($keys)) { $data=array_map(__function__,$data); return '['.join(',',$data).']'; } else {//不是有序数字下标的数组即视为关联数组 $a=array(); foreach ($data as $k=>$v) { $a[]=json_stringify_scalar(strval($k)).':'.json_stringify($v); } return '{'.join(',',$a).'}'; }}function json_stringify_scalar($v) { if (is_bool($v)) { $v = $v?'true':'false'; } else if (is_string($v)) { $v=addcslashes($v,\t\n\r\\/\\);//转义特殊字符 //将所有非ascii字符转换成unicode escape格式 $v=''.preg_replace_callback('|[^\x00-\x7f]+|','_unicode_escape',$v).''; } return (string)$v;}function _unicode_escape($s) { //warning:字符串必须为utf-8编码 $s=str_split(iconv('utf-8','ucs-2be',$s[0]),2); foreach ($s as $i=>$c) { $s[$i]=sprintf('\u%02x%02x',ord($c{0}),ord($c{1})); } return join('',$s);}
json decode而将json转换成php中的对象就没有那么简单了,自己写parser进行词法分析、语法分析是很累人的。反观在javascript中实现json parse就简单多了,因为json本身即是javascript语言的子集,直接使用eval方法,就能将json字符串转换成js中的对象。
其实,看到javascript中的eval方法,实在不能不联想到php也有一个eval,它们的功能是类似的,都是将字符串当作代码运行。不同的是,js中的eval执行js代码,php的eval执行php代码。trick就在这里:要让php能直接用eval方法解析json,只要将json代码转换成php格式的代码就行了!如对于下面的json:
{ name:cj, age:18, tags:[php,javascript,python,haskell], life:{ summary:too complex! }}
只要将其转换成这样的php代码就能直接eval了:
(object)array( name=>cj, age=>18, tags=>array(php,javascript,python,haskell), life=>(object)array( summary=>too complex! ))
而将json转换成php代码则只需很少的步骤与注意点:
最终的实现代码出人意料的简单:
/** * json decode * @param {string} $s the string json data. * @param {boolean} [$assoc=false] return assoc array if $assoc is true. * @return decode result corresponding object. */function json_parse($s,$assoc=false) { static $strings,$count=0; if (is_string($s)) { $s=trim($s); $strings=array(); //匹配字符串结束引号应该确保前面只能有偶数个'\' //如 ab\c中 \ 不能被视为字符串结束引号 $s=preg_replace_callback('/([\s\s]*?(?','null') ,$s); $s=preg_replace_callback('/#\d+#/',__function__,$s); //抑制错误,如{3##}能通过上面的安全检测但却无法转换成正确的php代码 @$data=eval(return $s;); $strings=$count=0;//gc return $data; } elseif (count($s)>1) {//存储字符串 $strings[]=_unicode_unescape(str_replace(array('$','\\/'),array('\\$','/'),$s[0])); return '#'.($count++).'#'; } else {//读取存储的值 $index=substr($s[0],1,strlen($s[0])-2); return $strings[$index]; }}function _unicode_unescape($data) { if (is_string($data)) { //匹配 unicode escape时,需要注意匹配'\u'前面只能有偶数个'\',如'\\u5409'不应被匹配 return preg_replace_callback( '/(? 性能和php 5.2之后的c实现的json方法相比,这里的实现自然要慢近百倍,根本不是一个数量级上的。 pear上有一个纯php实现的json库:services_json。作为比较,我做了一个简单的性能对比测试,结果是,services_json的encode方法比json_stringify方法慢三四倍,而services_json的decode方法更是比json_parse方法慢十几倍。 对于json_stringify方法,应该是主要得益于使用iconv先将utf-8字符串转换成ucs-2be,再转换成unicode转义序列的形式,自然要比services_json自己实现utf-8到unicode转义序列的转换性能更高。而json_parse方法,虽然一般的递归下降parser只需要扫描一次json字符串,而这里的实现会扫描多次字符串,但由于都是使用的php native字符串方法,再加上eval这个非常规手段,最终性能上反而要高出好几倍。
原文地址:http://jex.im/programming/json-eval-trick-in-php.html
http://www.bkjia.com/phpjc/626656.htmlwww.bkjia.comtruehttp://www.bkjia.com/phpjc/626656.htmltecharticlephp从5.2版本开始提供json_encode()和json_decode()函数,分别用于json的序例化和反序列化。不幸的是,现在仍然有许多主机运行着php5.2之前的版本...
沧州分类信息网,免费分类信息发布

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product