PHP——json_encode中文編碼問題

在PHP項目中會經常遇到中文亂碼,這是一個比較惱人的問題。不過,當需要將內容輸出到網頁上的時候,我們遵照以下兩個原則一般情況下是不會出現中文亂碼的。

第一就是在html頭部添加

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

第二點就是保證文件的編碼和meta設置的編碼一致。也就是說,如果我們第一條設置的charset爲UTF-8,那我們的文件編碼也要設置成UTF-8。二者保持一致即可。

當然上面是針對於網頁的情況,但是現在隨着Ajax在web應用中佔得比重越來越大,json格式的數據在數據傳輸中應用也越來越廣。因此在PHP中使用json_encode對數據進行json轉換的時候也會遇到中文亂碼或者是對中文進行編碼的問題。

舉個例子來說

$data = array('id'=>1,'name'=>'跡憶博客','parId'=>0);
echo json_encode($data);

上面代碼的輸出結果爲
{"id":1,"name":"\u8ff9\u5fc6\u535a\u5ba2","parId":0}

我們看,函數對中文’跡憶博客’進行了16進制轉碼。這不能說是錯誤,因爲16進製表示的就是正確的中文,我們拿到這個結果以後,在前端通過js同樣也可以得到我們想要的結果。但是,這樣使用起來還是比較麻煩的。當然情況也會根據PHP的版本的不同而有所變化。

對於PHP的一些版本其結果會是如下的情況

<pre name="code" class="php">{"id":1,"name":null,"parId":0}

中文無法被正確的解析出來。

沒有辦法,中文問題就是這麼麻煩。誰讓計算機不是中國人發明的呢。當然這些是有解決方法的,下面我們就來了解兩個解決的辦法。

一、通過json_encode第二個參數來解決

針對上面問題,在PHP>=5.4.0 的版本已經可以直接通過json_encode函數本身來解決。那就是第二個參數加上JSON_UNESCAPED_UNICODE。

$data = array('id'=>1,'name'=>'跡憶博客','parId'=>0);
echo json_encode($data, JSON_UNESCAPED_UNICODE);




現在就能得到正確的結果
{"id":1,"name":"跡憶博客","parId":0}

結果是能正確的得到了。但是,對於PHP的版本總不能讓大家都換成5.4及以上的版本吧。那對於5.4以下的版本應該怎麼處理呢?

二、通過url編碼解決中文問題

我們知道,在PHP中有兩個函數 urlencode 和 urldecode。我們可以通過urlencode函數將中文進行url編碼,這樣在字符串中就不會再有中文,也就不會遇到中文編碼的問題。

$str = “跡憶博客”;
echo urlencode($str);

對跡憶博客進行url編碼,其結果如下
%E8%BF%B9%E5%BF%86%E5%8D%9A%E5%AE%A2

所以說,我們將上面數組的name的值用urlencode編碼以後,再進行json格式轉化,那中文編碼的問題就不存在了。
$data = array('id'=>1,'name'=>urlencode('跡憶博客'),'parId'=>0);
$res = json_encode($data);
echo $res;

現在我們得到的結果就是name編碼以後的json字符串
{"id":1,"name":"%E8%BF%B9%E5%BF%86%E5%8D%9A%E5%AE%A2","parId":0}

最後再通過urldecode對url編碼的字符串進行解碼。當然urldecode解碼不用我們再去找對應的那一段編碼的字符串進行解碼。我們可以直接對整個字符串進行url解碼。urldecode會自動去檢測相應的url編碼的字符串對其進行解碼。
$data = array('id'=>1,'name'=>urlencode('跡憶博客'),'parId'=>0);
$res =urldecode(json_encode($data));
echo $res;
這樣其結果就是正確的了
{"id":1,"name":"跡憶博客","parId":0}

這種方法是沒有版本限制的,但是效率的話肯定會相對於第一種方法要慢一些。

針對第二個方法——通過url編碼解決中文問題——的封裝函數

現在問題來了,對於第二個方法,我們總不能在數組的每一箇中文前面都加上urlencode函數吧!這也是不現實的。那我們可以通過自己封裝json_encode函數來處理這樣的問題。

代碼如下

function onmpw_json_encode($data){
        if(is_object($data)) return false;
        if(is_array($data)){
            $data = deal_array($data);
        }
        return urldecode(json_encode($data));
}
function deal_array($data){
     if (is_array($data)) {
        foreach ($data as $key => $val) {
            if (is_array($val)) {
                                     //如果是多維數組,通過遞歸來處理多維數組
                $data[$key] = deal_array($val);
            } else {
                                     //對值進行url編碼
                $data[$key] = urlencode($val);
            }
        }
    } elseif (is_string($data)) {
        $data = urlencode($data);
    }
    return $data;
}

下面我們來看一個使用示例

$data = array(
            array('id'=>1,'name'=>'跡憶博客','parId'=>0),
            array('id'=>2,'name'=>'學無止境','parId'=>1),
            array('id'=>3,'name'=>'趣味雜談','parId'=>1),
            array('id'=>4,'name'=>'編程語言','parId'=>2),
            array('id'=>5,'name'=>'網絡','parId'=>2),
            array('id'=>6,'name'=>'算法','parId'=>2),
            array('id'=>7,'name'=>'操作系統','parId'=>2),
            array('id'=>8,'name'=>'數據庫','parId'=>2),
            array('id'=>9,'name'=>'WEB前端','parId'=>2),
            array('id'=>10,'name'=>'讀書','parId'=>3),
            array('id'=>11,'name'=>'觀點與感想','parId'=>3)
        );
$data = onmpw_json_encode($data);
echo $data;

現在我們得到了我們想要的結果
[{"id":"1","name":"跡憶博客","parId":"0"},{"id":"2","name":"學無止境","parId":"1"},{"id":"3","name":"趣味雜談","parId":"1"},{"id":"4","name":"編程語言","parId":"2"},{"id":"5","name":"網絡","parId":"2"},{"id":"6","name":"算法","parId":"2"},{"id":"7","name":"操作系統","parId":"2"},{"id":"8","name":"數據庫","parId":"2"},{"id":"9","name":"WEB前端","parId":"2"}, {"id":"10","name":"讀書","parId":"3"},{"id":"11","name":"觀點與感想","parId":"3"}]

中文編碼的問題很常見,我們大家要在實際情況中多總結。在以後的開發中再遇到類似的問題就可以很容易的解決了。

對於上面自定義的json_encode函數,我會把它封裝到一個公共類中。源代碼都在github上,我會持續將一些常用函數封裝到這個公共類中,歡迎大家點擊下載。希望這些對大家有所幫助。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章