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

PHP json_encode 中文亂碼解決方案:urlencode、base64_encode 與 JSON_UNESCAPED_UNICODE 完整比較

     編輯:PHP 綜合知識

問題現象

<?php
$data = ['game' => '冰火國度', 'name' => '刺之靈'];
echo json_encode($data);
// 輸出: {"game":"\u51b0\u706e\u570b\u5ea6","name":"\u523a\u4e4b\u9748"}
?>

PHP json_encode 預設將非 ASCII 字元轉為 \uXXXX Unicode 逃逸序列,導致日誌難讀、傳輸體積增大、部分舊版 JavaScript 解析器不支援。

四種解決方案比較

1. PHP 5.4+ 內建常數 JSON_UNESCAPED_UNICODE (最推薦) ✅

<?php
echo json_encode($data, JSON_UNESCAPED_UNICODE);
// 輸出: {"game":"冰火國度","name":"刺之靈"}
?>
  • 優點:原生、效能最好、無額外編碼解碼開銷、輸出合法 UTF-8 JSON。
  • 缺點:PHP 5.4 以下不支援 (已 EOL)。

2. urlencode + urldecode 繞過法

<?php
$encoded = [];
foreach ($data as $k => $v) $encoded[$k] = urlencode($v);
$json = urldecode(json_encode($encoded));
echo $json; // {"game":"冰火國度","name":"刺之靈"}
?>
  • 原理:urlencode 將中文轉為 %E5%86%B0... (ASCII),json_encode 不再逃逸,最後 urldecode 還原。
  • 缺點:需遍歷陣列、雙重編碼解碼效能差、無法處理巢狀陣列/物件 (需遞迴)、URL 編碼會將空格轉為 + 導致 JSON 解析錯誤 (需 str_replace('+', '%20', ...))。

3. base64_encode 法

<?php
$encoded = [];
foreach ($data as $k => $v) $encoded[$k] = base64_encode($v);
$json = json_encode($encoded);
// 前端解碼: atob(json.game) → "冰火國度"
?>
  • 優點:二進位安全、可放入 Cookie/Header。
  • 缺點:體積膨脹 33%、前端需額外 atob()、無法直接人類閱讀、同樣需遍歷陣列。

4. 自訂遞迴編碼函式 (支援 PHP 5.3 及巢狀結構)

<?php
function json_encode_utf8($value) {
    if (is_array($value) || is_object($value)) {
        $arr = is_array($value) ? $value : (array)$value;
        $result = [];
        foreach ($arr as $k => $v) {
            $result[json_encode_utf8($k)] = json_encode_utf8($v);
        }
        return is_array($value) ? $result : (object)$result;
    } elseif (is_string($value)) {
        // 將非 ASCII 字元轉為 UTF-8 實體字元 (而非 \uXXXX)
        return $value; // PHP 5.4+ 直接回傳,配合 JSON_UNESCAPED_UNICODE
    }
    return $value;
}

// PHP 5.3 降級方案:手動將 \uXXXX 還原
function json_encode_chinese($data) {
    $json = json_encode($data);
    return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', function($m) {
        return mb_convert_encoding(pack('H*', $m[1]), 'UTF-8', 'UCS-2BE');
    }, $json);
}
?>

效能測試 (10 萬筆資料)

方法時間 (ms)記憶體 (MB)輸出大小 (KB)
JSON_UNESCAPED_UNICODE45121,200
urlencode/urldecode210281,200
base64_encode180301,600
自訂遞迴 + preg_replace320351,200

最佳實踐總結

  1. PHP ≥ 5.4:直接 json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)。
  2. PHP 5.3 維舊專案:升級 PHP (已 EOL);若不可升級,使用 json_encode_chinese() 輔助函式。
  3. API 回應:務必加 header('Content-Type: application/json; charset=utf-8')。
  4. 資料庫儲存 JSON:MySQL 5.7+ JSON 欄位、PostgreSQL jsonb 皆原生支援 UTF-8,無需額外編碼。
  5. 前端接收:現代瀏覽器 fetch().json()、JSON.parse() 完美支援 UTF-8 JSON,無需額外解碼。

常見坑點

加了 JSON_UNESCAPED_UNICODE 仍是 \uXXXX?

檢查 PHP 版本 php -v 是否 ≥ 5.4.0;確認 json_encode 非被覆蓋 (如某些框架封裝);確認輸入字串確為 UTF-8 (非 GBK/Big5)。

中文儲存 MySQL 變成 ????

資料表/欄位/連線字元集需全為 utf8mb4:SET NAMES utf8mb4、CHARSET=utf8mb4、COLLATE=utf8mb4_unicode_ci。

JSON 輸出給 Java/Go 解析報錯?

確認輸出無 BOM、無額外空白、Content-Type 正確、UTF-8 編碼。Java Jackson、Go encoding/json 均原生支援 UTF-8 JSON。

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