zoukankan      html  css  js  c++  java
  • json_decode转换json数据为数组出现的问题!

      json_decode这个函数是json_encode的反函数,一般传递数据的时候为了压缩数据,会将数组格式的数据转换成json格式,用到的函数就是json_encode,然后接收到数据之后再用json_decode转换回数组,这里本来应该不会出现什么问题, 但也有意外,这个意外应该可以说也是自己造成,bom头导致的bug,其实准确来说也不算bug,但就是让你的数据无法正确转换回来;

      bom头的产生应该是你的文件在windows下用记事本这些东西编辑过之后的后果,可能无意之间就给这个bug的产生带来了隐患;但是就算出现这个问题也不用慌张, 凡是都有解决的办法;

      json_decode($json)之后可能出现返回空,null等结果,这个时候一般都是json格式出问题, 可以用json_last_error()来检查,json_last_error()函数的使用方式就是在json_decode之后添加这个函数, 函数会返回值,返回0说明格式没错, 我遇到的事返回4,说明格式错误,之前用json在线检测工具检测数据,显示是正确的,这两个居然矛盾,让我大惑不解,不过如果知道bom头这个概念立马就应该反应过来, bom头是看不见的, 所以转换的时候前面多了三个字节,当然看不见, 在线检测的时候复制这个数据没有bom头的三个字节,当然也就正确了, 所以立马用$json=substr($json,3);这个函数,去掉头部的三个字节, 转换之后ok了;

      问题解决之后感概万千, 因为这个问题我找了两天,本来问题影藏的不深,只是代码不是自己写的, 其次本地环境与服务器环境不一致, 反正诸多原因,一直没想到会是这个问题;最后一步一步排查,锁定这个函数;感觉以后编辑文件一定不能图方便, 一个小错误就直接用记事本大概编辑一下就行了, 很容易出现这个bom头问题;而且自己还不知道;

    这里贴出一段代码, 可以去除网站所有文件的bom头信息;

     1 <?php
     2 if (isset($_GET['dir'])){ //设置文件目录
     3 $basedir=$_GET['dir'];
     4 }else{
     5 $basedir = '.';
     6 }
     7 $auto = 1;
     8 checkdir($basedir);
     9 function checkdir($basedir){
    10 if ($dh = opendir($basedir)) {
    11 while (($file = readdir($dh)) !== false) {
    12 if ($file != '.' && $file != '..'){
    13 if (!is_dir($basedir."/".$file)) {
    14 echo "filename: $basedir/$file ".checkBOM("$basedir/$file")." <br>";
    15 }else{
    16 $dirname = $basedir."/".$file;
    17 checkdir($dirname);
    18 }
    19 }
    20 }
    21 closedir($dh);
    22 }
    23 }
    24 function checkBOM ($filename) {
    25 global $auto;
    26 $contents = file_get_contents($filename);
    27 $charset[1] = substr($contents, 0, 1);
    28 $charset[2] = substr($contents, 1, 1);
    29 $charset[3] = substr($contents, 2, 1);
    30 if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) {
    31 if ($auto == 1) {
    32 $rest = substr($contents, 3);
    33 rewrite ($filename, $rest);
    34 return ("<font color=red>BOM found, automatically removed._<a href=http://www.k686.com>http://www.k686.com</a></font>");
    35 } else {
    36 return ("<font color=red>BOM found.</font>");
    37 }
    38 }
    39 else return ("BOM Not Found.");
    40 }
    41 function rewrite ($filename, $data) {
    42 $filenum = fopen($filename, "w");
    43 flock($filenum, LOCK_EX);
    44 fwrite($filenum, $data);
    45 fclose($filenum);
    46 }

    这段代码也是网上找来的, 用了觉得还是蛮方便,不过不敢在服务器上用,以免造成位置的别的什么错误;

    所以想到一个折中的办法, 现在本地跑了一下,把出现bom的文件全都替换,然后服务器上的问题并没有解决,然后又在转换json的时候添加了一个判断

    if(preg_match('/^xEFxBBxBF/',$json))
    {
    $json=substr($json,3);
    }

    这样如果检测得到bom头信息去掉就好了;

  • 相关阅读:
    redis conf 中文详解
    sed 用法记录
    MySQL数据库的各种存储引擎详解
    MySQL数据库char与varchar的区别分析及使用建议
    从一个乘法来分析C语言
    排它平方数
    高斯日记
    SUID或SGID程序中能不能用system函数
    【转载】GDB反向调试(Reverse Debugging)
    setuid函数解析
  • 原文地址:https://www.cnblogs.com/zqphp/p/4885473.html
Copyright © 2011-2022 走看看