首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 5.2 中 json_encode 處理中文與 GBK 編碼的完美解決方案

     編輯:PHP 相關知識

PHP 5.2 引入 JSON 擴展,但 json_encode 對中文處理存在兩大痛點:GBK/GB2312 編碼字符串直接返回空字符;UTF-8 中文被轉為 Unicode 轉義序列(如 \u4e2d\u6587),導致傳輸體積增大、前端解析麻煩。本文提供多種兼容方案。

問題根因分析

  • PHP 5.2 json_encode 要求輸入必須是 UTF-8,非 UTF-8 直接返回 false 或空字符
  • UTF-8 中文預設輸出 Unicode 轉義,PHP 5.4+ 才支援 JSON_UNESCAPED_UNICODE 選項

方案一:封裝類統一處理編碼轉換與 Unicode 還原(推薦 PHP 5.2/5.3)

<?php
/**
 * JSON 兼容處理類
 * 解決:GBK 轉 UTF-8、Unicode 轉義還原為中文
 */
class Json {
    /**
     * 編碼:自動處理編碼轉換 + Unicode 還原
     * @param mixed $data 待編碼數據(支援陣列、物件、字符串)
     * @param string $inputCharset 輸入數據編碼,預設 UTF-8
     * @return string JSON 字符串
     */
    public static function encode($data, $inputCharset = 'UTF-8') {
        // 1. 統一轉為 UTF-8
        if (strtoupper($inputCharset) !== 'UTF-8') {
            $data = self::convertToUtf8($data, $inputCharset);
        }
        
        // 2. json_encode
        $json = json_encode($data);
        
        // 3. 將 \uXXXX 還原為 UTF-8 字符(PHP 5.2/5.3 核心技巧)
        // 使用 preg_replace_callback 避免已棄用的 /e 修飾符
        $json = preg_replace_callback(
            '/\\\\u([0-9a-fA-F]{4})/',
            function ($matches) {
                return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UCS-2BE');
            },
            $json
        );
        
        return $json;
    }
    
    /**
     * 解碼:自動處理編碼
     */
    public static function decode($json, $outputCharset = 'UTF-8') {
        $data = json_decode($json, true);
        if (strtoupper($outputCharset) !== 'UTF-8') {
            $data = self::convertFromUtf8($data, $outputCharset);
        }
        return $data;
    }
    
    // 遞歸轉換陣列/物件編碼到 UTF-8
    private static function convertToUtf8($data, $fromCharset) {
        if (is_array($data)) {
            foreach ($data as $key => $val) {
                $data[$key] = self::convertToUtf8($val, $fromCharset);
            }
            return $data;
        } elseif (is_object($data)) {
            foreach ($data as $key => $val) {
                $data->$key = self::convertToUtf8($val, $fromCharset);
            }
            return $data;
        } elseif (is_string($data)) {
            return mb_convert_encoding($data, 'UTF-8', $fromCharset);
        }
        return $data;
    }
    
    // 遞歸轉換 UTF-8 到目標編碼
    private static function convertFromUtf8($data, $toCharset) {
        if (is_array($data)) {
            foreach ($data as $key => $val) {
                $data[$key] = self::convertFromUtf8($val, $toCharset);
            }
            return $data;
        } elseif (is_object($data)) {
            foreach ($data as $key => $val) {
                $data->$key = self::convertFromUtf8($val, $toCharset);
            }
            return $data;
        } elseif (is_string($data)) {
            return mb_convert_encoding($data, $toCharset, 'UTF-8');
        }
        return $data;
    }
}

// 使用示例
$arr = ['name' => '中文測試', 'city' => '北京'];
// GBK 環境下
echo Json::encode($arr, 'GBK'); 
// 輸出: {"name":"中文測試","city":"北京"} 而非 {"name":"\u4e2d\u6587\u6d4b\u8bd5",...}

方案二:前端 JavaScript 還原 Unicode(無需修改 PHP)

若無法升級 PHP 或修改後端,可在前端接收後處理:

<script>
// 將 \uXXXX 還原為中文
function unicodeToChinese(str) {
    return str.replace(/\\u([0-9a-fA-F]{4})/g, function (match, grp) {
        return String.fromCharCode(parseInt(grp, 16));
    });
}

// 使用
var jsonStr = '{"name":"\\u4e2d\\u6587","city":"\\u5317\\u4eac"}';
var obj = JSON.parse(jsonStr);
obj.name = unicodeToChinese(obj.name); // "中文"
obj.city = unicodeToChinese(obj.city); // "北京"
</script>

方案三:升級 PHP 5.4+ 使用原生選項(最佳長期方案)

<?php
// PHP 5.4+ 直接支援
$json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

// 完整選項說明
$options = 0;
$options |= JSON_UNESCAPED_UNICODE;   // 不轉義 Unicode,直接輸出中文
$options |= JSON_UNESCAPED_SLASHES;   // 不轉義 /
$options |= JSON_NUMERIC_CHECK;       // 數值字符串轉為數字
$options |= JSON_PRETTY_PRINT;        // 格式化輸出(調試用)
$json = json_encode($data, $options);

方案四:使用 mb_convert_encoding 預處理(快速修復)

<?php
// 編碼前強制轉 UTF-8
function jsonEncodeCompat($data, $inputCharset = 'UTF-8') {
    if (strtoupper($inputCharset) !== 'UTF-8') {
        $data = mb_convert_encoding($data, 'UTF-8', $inputCharset);
    }
    // PHP 5.3+ 可用 JSON_FORCE_OBJECT 等選項
    return json_encode($data);
}

// 解碼後轉回目標編碼
function jsonDecodeCompat($json, $outputCharset = 'UTF-8') {
    $data = json_decode($json, true);
    if (strtoupper($outputCharset) !== 'UTF-8') {
        $data = mb_convert_encoding($data, $outputCharset, 'UTF-8');
    }
    return $data;
}

編碼檢測與轉換最佳實踐

場景建議方案關鍵點
新項目/可升級 PHP升級至 PHP 7.4+,使用 JSON_UNESCAPED_UNICODE原生支援、效能最佳、維護成本最低
維護老項目 PHP 5.2/5.3封裝 Json 類(方案一)統一入口、自動處理編碼、前端無感知
無法修改後端前端 JS 還原 Unicode零後端改動、適用第三方 API
混合編碼環境統一內部使用 UTF-8,邊界處轉換資料庫、模板、API 統一 UTF-8,避免亂碼源頭

常見坑點提醒

  • ❌ 直接對 GBK 字符串調用 json_encode → 必須先 mb_convert_encoding($str, 'UTF-8', 'GBK')
  • ❌ 使用 preg_replace /e 修飾符 → PHP 7.0+ 已移除,必須用 preg_replace_callback
  • ❌ 忽略巢狀陣列/物件的編碼轉換 → 需遞歸處理所有字符串值
  • ✅ 資料庫連接設定 charset=utf8mb4 → 從源頭保證 UTF-8
  • ✅ HTML 頁面聲明 <meta charset="utf-8"> → 瀏覽器正確解碼

JSON 中文處理的核心原則是:內部統一 UTF-8,邊界自動轉換。PHP 5.2/5.3 時代雖有缺陷,但通過封裝類或前端輔助可完美解決。現代項目請務必升級 PHP 版本,享受原生 JSON_UNESCAPED_UNICODE 帶來的簡潔與高效。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved