最新消息:

php里json_decode无法解析返回空(null)的原因(php与BOM头)

PHP admin 6560浏览 0评论

json_decode是php5.2.0之后新增的一个PHP内置函数,其作用是对JSON 格式的字符串进行编码.
json_decode的语法规则:json_decode ( string $json [, bool $assoc = false [, int $depth = 512 [, int $options = 0 ]]] )

json_decode 接受一个 JSON 格式的字符串并且把它转换为 PHP 变量 ,当该参数$assoc为 TRUE 时,将返回 array 否则返回 object 。

JSON 格式的字符串
$json = ‘{“a”:”php”,”b”:”mysql”,”c”:3}’;
其中a为键,php为a的键值。

我们来看一个实例:

<?php   
$json = '{"a":"php","b":"mysql","c":3}';  
$json_Class=json_decode($json);   
$json_Array=json_decode($json, true);   
print_r($json_Class);   
print_r($json_Array);   
      
?>
 程序输出:

stdClass Object (
[a] => php
[b] => mysql
[c] => 3 )
Array (
[a] => php
[b] => mysql
[c] => 3 )

————————————————————————————————————————-

php5.2以后自带json_decode函数,但是对json文本串的格式要求非常严格。

很可能使用该函数得到的返回值是NULL

可以使用使用json_last_error()函数获取到的返回值来帮助我们判断出问题的原因。

其中如果提示错误JSON_ERROR_SYNTAX(Syntax error),表示json串格式错误。

可以通过以下几个方式排错:

1. json字符串必须以双引号包含

$output = str_replace(“‘”, ‘”‘, $output);

2. json字符串必须是utf8编码
$output = iconv(‘gbk’, ‘utf8’, $output);

3.不能有多余的逗号 如:[1,2,]
用正则替换掉,preg_replace(‘/,\s*([\]}])/m’, ‘$1’, $output)

————————————————————————————————————-

<?php
$checkLogin = file_get_contents("http://yourwebsite.com/JsonData");

// This will remove unwanted characters.
// Check http://www.php.net/chr for details
for ($i = 0; $i <= 31; ++$i) { 
    $checkLogin = str_replace(chr($i), "", $checkLogin); 
}
$checkLogin = str_replace(chr(127), "", $checkLogin);

// This is the most common part
// Some file begins with 'efbbbf' to mark the beginning of the file. (binary level)
// here we detect it and we remove it, basically it's the first 3 characters 
if (0 === strpos(bin2hex($checkLogin), 'efbbbf')) {
   $checkLogin = substr($checkLogin, 3);
}

$checkLogin = json_decode( $checkLogin );
print_r($checkLogin);
?>

当php中通过多次调用得到的json字符串时,有可能开头有多个efbbbf,所有一般要如下处理:

	$search_data_tmp = Get_search(htmlspecialchars(trim($_POST['keyword'])), '', '', $key, $SITE['url']);
	for ($i = 0; $i <= 31; ++$i)
	{
    	$search_data_tmp = str_replace(chr($i), "", $search_data_tmp);
    }
    $search_data_tmp = str_replace(chr(127), "", $search_data_tmp);
    while(0 === strpos(bin2hex($search_data_tmp), 'efbbbf'))
    {
    	$search_data_tmp = substr($search_data_tmp, 3);
    }

 

记一次“惨痛”的上线bug经历:php与BOM头

转自:http://weibo.com/p/1001603783734905204405

经验往往是伴随着“惨痛”的教训而来,比如说最近的这次。事情的起因,源于最近的一次上线:手机客户端的“微博视频广场”代码修改上线后,页面突然异常,模块展示各种混乱,整个视频广场都变得“不好了”。。。
1.查找bug原因
有了问题就要查找原因。首先想到的是调用接口返回的数据异常。但是手动调用接口(浏览器调用&终端curl调用),返回的json格式数据都是正确的,接口输出“看起来”没有问题。
无奈之下,只得求助于接口调用方,经过不断的打断点调试,终于在接口输出json数据的开头,发现了诡异的“\ufeff”字符(见下图)!!!而恰恰由于这几个字符,导致了接口输出的json串解析失败!
jinglingshu_2014-12-04_09-03-061    马上百度之,发现返回结果中都提到了“BOM头”!原来是BOM头捣的鬼!bug的原因终于找到了!
也许看到这,你不禁想问什么是BOM头?不要急,下面就跟大家介绍下~
2.php与BOM头
BOM(Byte Order Mark)是一个字节顺序标签,类似一个标记,又叫签名,用来告诉编辑器当前文件采用何种编码,方便编辑器识别。除了unicode编码,一般的编码集并 不会出现bom头。对于utf-16和utf-32,如果不指定bom头,解析程序就默认为ansi编码,从而出现乱码;而对于utf-8,BOM头指定 与否,解析程序都可判断。
现在几乎所有的文本编辑软件都可以显示并编辑UTF-8编码的文件,但其中很多的表现并不理想。类似WINDOWS自带的记事本等软件,在保存一个以 UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符0xEF、0xBB和0xBF,即BOM。对于一般的文件,这样做并不会产生麻烦。但对 于 PHP来说,BOM是个大麻烦。因为PHP并不会忽略BOM,所以在读取、包含或者引用这些文件时,会把BOM作为该文件开头正文的一部分。同时根据嵌入 式语言的特点,这串字符最终将被直接执行(显示)出来。
回到我们的问题中,由于有个配置文件在开发时用WINDOWS自带的记事本编辑保存过,导致这个文件在开头加入了BOM头,而这个配置文件在各个php接口脚本中都被读取过,从而导致接口输出的json格式数据前面多了BOM头。
3.bug解决办法
找到了问题原因,解决方法就很简单了:把utf-8编码文件的BOM头去掉。可以编写程序,检测文件头的三个字符是否为0xEF、0xBB和0xBF,如 果是的话,直接删除掉即可;也可以用下文提到的靠谱的编辑器,打开文件重新编辑,设置为无BOM头的utf-8编码。例如Notepad++的使用如下 图:
jinglingshu_2014-12-04_09-03-06
4.经验总结
写到这里回头看,其实问题的原因很简单,但却很隐蔽,导致排查问题、查找原因的过程十分痛苦纠结。事后我也在不断思考,试图去总结些普遍试用的经验教训,以避免同类问题的再次发生。以下是一点浅见。
最最重要的教训,就是不要忽略测试!这里说的测试,不是自己开发完自己测,而是由QA,在上线前执行标准化的测试流程!这也是避免非环境原因导致隐蔽bug的有效措施之一!
其次,就是上线前通过svn合代码进行code review时,不忽视任何细小的改动。BOM头是在文件开头添加了3个字符,在新旧代码的对比中,其实这种改动svn也会检测出来;但限于svn编辑器 无法显示BOM头,直观的看,文件的开头好像多了个空格,但实际什么都没有。遇到这种情况,很大可能性就是BOM头捣的鬼!
此外,在编辑、更改任何文本文件时,不要使用乱加BOM的编辑器!尤其是WINDOWS下,不要使用记事本做编辑器!!!
推荐几个靠谱的编辑器:Editplus,Notepad++,EmEditor,UltraEdit,Dreamweaver(需要取消‘添加BOM’的相关选项)等。
5.BOM头对php程序的其他危害
BOM头对php程序的危害,最典型、最严重的,还不是上文提到的情况。如果在涉及到COOKIE实现的php文件中有BOM头,由于在COOKIE送出 前PHP已经送出了文件头,那么受COOKIE送出机制的限制,COOKIE将无法送出,导致登入和登出功能失效!一切依赖COOKIE、SESSION 实现的功能都将无效!
另外一个典型危害:如果php程序实现xml格式的数据输出,并且php文件有BOM头,那么会造成输出的xml格式数据解析失败!

转载请注明:jinglingshu的博客 » php里json_decode无法解析返回空(null)的原因(php与BOM头)

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址