关于PHP在数组对象与JSON数据之间的转换问题(编码问题)  

 PHP在 5.x以后提供json_ecode 与 json_decode 两个函数来处理 数组与JSON数据之间的转换。但是它们并未很好的处理存在UTF-8或者GBK中文字符的数组,常常会返回NULL值。下面有两个函数可以代替它们来使用:

 

 

//数组转换成JSON格式核心函数
function array2json($arr) {
  //  if(function_exists('json_encode')) return json_encode($arr); //Lastest versions of PHP already has this functionality.
    $parts = array();
    $is_list = false;

    //Find out if the given array is a numerical array
    $keys = array_keys($arr);
    $max_length = count($arr)-1;
    if(($keys[0] == 0) and ($keys[$max_length] == $max_length)) {//See if the first key is 0 and last key is length - 1
        $is_list = true;
        for($i=0; $i<count($keys); $i++) { //See if each key correspondes to its position
            if($i != $keys[$i]) { //A key fails at position check.
                $is_list = false; //It is an associative array.
                break;
            }
        }
    }

    foreach($arr as $key=>$value) {
        if(is_array($value)) { //Custom handling for arrays
            if($is_list) $parts[] = array2json($value); /* :RECURSION: */
            else $parts[] = '"' . $key . '":' . array2json($value); /* :RECURSION: */
        } else {
            $str = '';
            if(!$is_list) $str = '"' . $key . '":';

            //Custom handling for multiple data types
            if(is_numeric($value)) $str .= $value; //Numbers
            elseif($value === false) $str .= 'false'; //The booleans
            elseif($value === true) $str .= 'true';
            else $str .= '"' . addslashes($value) . '"'; //All other things
            // :TODO: Is there any more datatype we should be in the lookout for? (Object?)

            $parts[] = $str;
        }
    }
    $json = implode(',',$parts);
    
    if($is_list) return '[' . $json . ']';//Return numerical JSON
    return '{' . $json . '}';//Return associative JSON
}

 

 

 

//下面是将JSON转换成数组,分为UTF-8格式的和GBK格式,用法如下:

 

/*$array_gbk = jsonDecode( $jsonString );   
  
$array_utf8 = jsonDecode( $jsonString , 'utf-8' );  */

 

 

 

function unicode_encode($name)   
{   
    $name = iconv('UTF-8', 'UCS-2', $name);   
    $len = strlen($name);   
    $str = '';   
    for ($i = 0; $i < $len - 1; $i = $i + 2)   
    {   
        $c = $name[$i];   
        $c2 = $name[$i + 1];   
        if (ord($c) > 0)   
        {   //两个字节的文字   
            $str .= '/u'.base_convert(ord($c), 10, 16).base_convert(ord($c2), 10, 16);   
        }   
        else  
        {   
            $str .= $c2;   
        }   
    }   
    return $str;   
}   
  
//将UNICODE编码后的内容进行解码   
function unicode_decode($name)   
{   
    //转换编码,将Unicode编码转换成可以浏览的utf-8编码   
    $pattern = '/(///u([/w]{4}))/i';   
    $name = preg_replace_callback( $pattern , '_unicode_decode' , $name );   
    return $name;   
}   
  
function _unicode_decode( $str ) {   
    $str = $str[0];   
    $name = '';   
    $code = base_convert(substr($str, 2, 2), 16, 10);   
    $code2 = base_convert(substr($str, 4), 16, 10);   
    $c = chr($code).chr($code2);   
    $c = iconv('UCS-2', 'UTF-8', $c);   
    $name .= $c;   
  
    return $name;   
}   
  
  
function jsonDecode( $json , $to_encode = 'gbk' , & $i = 0 ) {   
    if ( null === $i ) {   
        $i = 0;   
    }   
  
    for( ; $i < strlen( $json ) ; $i ++ ) {        
        $chr = $json[$i];   
  
        switch( $chr ) {   
            case '"' :   
            case "'" :  
                //字符串         
                $i ++;  
                $val = '';  
                while( $json[$i] != $chr || $lastChr == '//' ) {  
                    $lastChr = $json[$i];  
                    $val .= $lastChr;  
                    $i ++;  
                      
                }  
                ++ $i;  
                  
                //字符串处理  
                  
                //unicode 转汉字  
                $val = unicode_decode( $val );  
                if ( strtolower( str_ireplace( '-' , '' , $to_encode ) ) !== 'utf8' ) {  
                    $val = mb_convert_encoding( $val , $to_encode , 'utf-8' );  
                }  
                $val = stripslashes( $val );                  
                return $val;  
                break;  
            case 'a' :  
            case 'b' :  
            case 'c' :  
            case 'd':  
            case 'e':  
            case 'f':  
            case 'g':  
            case 'h':  
            case 'i':  
            case 'j':  
            case 'k':  
            case 'l':  
            case 'm':  
            case 'n':  
            case 'o':  
            case 'p':  
            case 'q':  
            case 'r':  
            case 's':  
            case 't':  
            case 'u':  
            case 'v':  
            case 'w':  
            case 'x':  
            case 'y':  
            case 'z':  
            case 'A' :  
            case 'B' :  
            case 'C' :  
            case 'D':  
            case 'E':  
            case 'F':  
            case 'G':  
            case 'H':  
            case 'I':  
            case 'J':  
            case 'K':  
            case 'L':  
            case 'M':  
            case 'N':  
            case 'O':  
            case 'P':  
            case 'Q':  
            case 'R':  
            case 'S':  
            case 'T':  
            case 'U':  
            case 'V':  
            case 'W':  
            case 'X':  
            case 'Y':  
            case 'Z':     
            case '0':  
            case '1':  
            case '2':  
            case '3':  
            case '4':  
            case '5':  
            case '6':  
            case '7':  
            case '8':  
            case '9':  
              
                //字符串  
                if ( trim( $chr ) === '' ) {  
                    continue;  
                }  
                $val = $chr;  
                while( preg_match( '#^[a-zA-Z0-9/.]$#' , $json[++$i] ) ) {  
                    $val .= $json[$i];                                    
                }  
                $lVal = strtolower( $val );  
                if ( $lVal == 'true' ) {  
                    return true;  
                }  
                if ( $lVal == 'false' ) {  
                    return false;  
                }  
                if ( preg_match( '#^[0-9/.]+$#' , $lVal ) ) {  
                    return $val + 0;  
                }  
                return $val;  
            case '{' :  
                $val = array();  
                $i ++;  
                $key = '';  
                while( $json[$i] != '}' ) {  
                    $key .= $json[$i];  
                    $i ++;  
                    if ( $json[$i] == ':' ) {  
                        $key = ltrim( $key );  
                        $key = ltrim( $key , ',' ); //去除,  
                        $key = trim( $key );//去两边的空白  
                        if ( preg_match( '#^"(.+?)"$#' , $key , $m ) ) {  
                            $key = $m[1];  
                        }  
                        if ( preg_match( '#^/'(.+?)/'$#' , $key , $m ) ) {   
                            $key = $m[1];   
                        }   
                        ++ $i;   
                        $val[$key] = jsonDecode( $json , $to_encode , $i );   
                        $key = '';                         
                    }                      
                }   
                ++ $i;   
                return $val;   
                break;   
            case '[' :   
                $val = array();   
                $i ++;   
                $t = 0;   
                while( $json[$i] != ']' ) {   
                    if ( $json[$i] == ',' ) {   
                        $i ++;   
                        continue;   
                    }                      
                    $val[] = jsonDecode( $json , $to_encode  , $i );                       
                   
                }   
                   
                $i ++;   
                return $val;   
                break;   
        }   
    }   
    return NULL ;   
}