php json 不带引号,php使用json与js交换数据——不带双引号的json数据解析

PHP和Javascript在某些方面总是惊人的相似,可是有时候却让人摸不着头脑。

案例1:Javascript原生支持的json格式,在编码上比PHP体积小,例如

$arr = array(array("name" => "php"));

$json = json_encode($arr);

echo $json;

//会输出[{"name":"php"}]

?>

而在Js中,上面的案例[{"name":"php"}]是可以被任何浏览器识别的,但是Javascript还支持更简单的写法var string = [{name:"php"}];

js可以省略属性名双引号,所以js占用体积小。可是,当我们使用js构造的json字符没有双引号直接传递给php之后,例如:

$json = '[{name:"php"}]';

$brr = json_decode($json, true);

var_dump($brr);

//坑爹的php竟然输出NULL

?>

介于这两种语言的差异,可以使用正则表达式来修正。

$json = '[{name:"php"}]';

$php = preg_replace('/(\w+)\s*:\s*/is', '"$1":', $json);

$crr = json_decode($php, true);

//这样就能正确解析js传入的json了

当然,如果你希望js从php获取的json的key不带双引号以节省传输量,还可以这样:

$arr = array(array("name" => "php"));

$json = json_encode($arr);

$js = preg_replace('/"(\w+)"\s*:\s*/is', '$1:', $json);

echo $js;

//将会输出:[{name:"php"}]

重大更新:如果你的数据非常简单,键值对中没有冒号,单双引号等特殊字符,上面的即可满足,可是一旦出现这些特殊符号,正则匹配将会出错。下面的复杂正则表达式希望可以解决这些问题:

header("content-type:text/html; charset=utf-8");

//变态情况下的数据

$json = '[{ id : \'301\' , pId : 11 ,name:"%u5730%u7403%u6751%2819%29",url:"#",target:"_self",iconSkin:"pIcon03"},{id:"111",pId:"11",name:"PK%289%29",url:"#",target:"_self",iconSkin:"pIcon03"},{id:"1",pId:0,name:"%u9986%u85CF%u5206%u7C7B",url:"javascript:void(0);",target:"_self",open:true,iconSkin:"pIcon01"}]';

$arr = json_decode_fix($json);

var_dump($arr);

//极有可能出现的情况

$json = '[{a:"3:4"},{b:"7:8"}]';

$brr = json_decode_fix($json);

var_dump($brr);

/**

* php解码js版本的json,兼容单引号和不带双引号情况

* @param string $json

* @return array

*/

function json_decode_fix($json)

{

$json = str_replace("',", '",', $json);

// 修复子元素带有'{"

if(($first = strpos($json, "'{\"")) !== false) {

$json = str_replace("'{\"", "'{\\\"", $json);

$last = strpos($json, "}");

$middle = str_replace('":', '\":', substr($json, $first, $last-$first));

$json = substr_replace($json, $middle, $first, $last-$first);

}

$result = json_decode($json, true);

if($result)

{

return $result;

}else{

//不允许以纯数字作为键名或在键名或值处出现冒号,否则可能修复失败

$pattern = '/(\w+\s*):([\s*\"\'|\d*]|true|false)+/is';

$json = preg_replace_callback($pattern, function($matches){

//处理纯数字或布尔值,其冒号之后为true、false、纯数字而非单双引号

$index = strpos($matches[0], ':');

$key = trim($matches[0]);

$last = substr($key, -1);

if($last === '"')

{

if(strpos($key, '""') !== false) {

$key = rtrim($key, '" ').'"';

}else{

$key = rtrim($key, '" ');

}

return '"'.trim(substr($key, 0, $index)).'":'.trim(substr($key, $index+1)).'"';

}else if($last === "'")

{

$key = rtrim($key, "' ");

return '"'.trim(substr($key, 0, $index)).'":"'.trim(substr($key, $index+1), "' ").(substr($key, $index+1) === false ? '' : '"');

}else{

$left = trim(substr($key, 0, $index));

return is_numeric($left) ? $matches[0] : '"'.trim(substr($key, 0, $index)).'":'.substr($key, $index+1);

}

}, $json);

return json_decode($json, true);

}

}

费了九牛二虎之力才编写出这个函数,测试虽然也花了很长时间,但是也不能面面俱到。

以上函数中,针对特殊函数类型如布尔值true和false,整数类型纯数字不带双引号的情况做了兼容。此外,针对值中含有冒号等特殊字符的情况也做了特殊处理。

案例2:PHP使用json_encode会导致中文汉字被编码为unicode,输出到js中虽然可以被识别,但是可读性大大降低。例如

$arr = array(array("word" => "中文"));

$json = json_encode($arr);

echo $json;

//会输出[{"word":"\u4e2d\u6587"}]

这时,通过js返回给浏览器时,中文会以unicode存在,对调试工作带来不便。这里介绍一个自动识别中文且不编码的方法,代码如下:

/**

*@功能:json_encode不编译中文成unicod

*@参数:类型为array,$array是待编码的数组

*@返回:类型为string

*/

function json_encode_cn($array)

{

arrayRecursive($array, 'urlencode', true);

$json = json_encode($array);

return urldecode($json);

}

/**************************************************************

*

*    使用特定function对数组中所有元素做处理

*    @param  string  &$array     要处理的字符串

*    @param  string  $function   要执行的函数

*    @return boolean $apply_to_keys_also     是否也应用到key上

*    @access public

*

*************************************************************/

function arrayRecursive(&$array, $function, $apply_to_keys_also = false)

{

static $recursive_counter = 0;

if (++$recursive_counter > 1000) {

die('possible deep recursion attack');

}

if(!empty($array))

{

foreach ($array as $key => $value) {

if (is_array($value)) {

arrayRecursive($array[$key], $function, $apply_to_keys_also);

} else {

$array[$key] = $function($value);

}

if ($apply_to_keys_also && is_string($key)) {

$new_key = $function($key);

if ($new_key != $key) {

$array[$new_key] = $array[$key];

unset($array[$key]);

}

}

}

}

$recursive_counter--;

}

案例2可以改为:header("content-type:text/html; charset=utf-8");

$arr = array(array("word" => "中文"));

$json = json_encode_cn($arr);

echo $json;

//会输出[{"word":"中文"}]

调试完成之后,上线的时候将json_encode_cn批量替换为json_encode即可,不替换也应该不会影响使用。

转载随意!带上文章地址吧。

你可能感兴趣的:(php,json,不带引号)