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

PHP 5.3/5.4 以下版本 JSON 中文不轉義解決方案:json_encode_ex 相容實作

     編輯:PHP 綜合知識

問題背景

PHP 5.4 之前 json_encode() 強制將 Unicode 字元(含中文)轉為 \uXXXX 格式。若對接系統(如 Java)簽名驗證基於原始字串,轉義會導致簽名不匹配。PHP 5.4+ 引入 JSON_UNESCAPED_UNICODE 選項,舊版本需自行實作。

相容性封裝函數 json_encode_ex()

<?php
/**
 * 跨版本 JSON 編碼,支援中文不轉義
 * PHP 5.4+ 使用原生選項,舊版本手動實作
 */
function json_encode_ex($var, int $options = 0): string {
    // PHP 5.4+ 直接使用原生
    if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
        return json_encode($var, $options | JSON_UNESCAPED_UNICODE);
    }

    // --- PHP 5.3 及以下 手動實作 ---
    static $replacements = [
        ['\\', '/', "\n", "\t", "\r", "\b", "\f", '"'],
        ['\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\\"']
    ];

    // 純量值
    if (is_scalar($var)) {
        if (is_bool($var)) return $var ? 'true' : 'false';
        if (is_null($var)) return 'null';
        if (is_float($var)) return (string)$var;
        if (is_int($var)) return (string)$var;
        // 字串:僅轉義控制字元與雙引號,保留 Unicode
        return '"' . str_replace($replacements[0], $replacements[1], (string)$var) . '"';
    }

    // 非陣列/物件拋異常
    if (!is_array($var) && !is_object($var)) {
        throw new InvalidArgumentException('json_encode_ex: 不支援的型別 ' . gettype($var));
    }

    // 判斷是關聯陣列還是索引陣列
    $isAssoc = false;
    $expectedKey = 0;
    foreach ($var as $k => $v) {
        if (!is_int($k) || $k !== $expectedKey++) {
            $isAssoc = true;
            break;
        }
    }

    $parts = [];
    if ($isAssoc) {
        foreach ($var as $k => $v) {
            // 鍵名必須為字串
            $keyStr = json_encode_ex((string)$k);
            $parts[] = $keyStr . ':' . json_encode_ex($v);
        }
        return '{' . implode(',', $parts) . '}';
    } else {
        foreach ($var as $v) {
            $parts[] = json_encode_ex($v);
        }
        return '[' . implode(',', $parts) . ']';
    }
}

// --- 使用範例 ---
$data = [
    'orderCode' => '1401160935542399',
    'creator' => '生活用品測試小屋',
    'items' => ['商品A', '商品B'],
    'meta' => (object)['id' => 123, 'tag' => '測試']
];

echo json_encode_ex($data);
// 輸出: {"orderCode":"1401160935542399","creator":"生活用品測試小屋","items":["商品A","商品B"],"meta":{"id":123,"tag":"測試"}}
?>

實作細節說明

處理項目說明
Unicode 保留不做 \uXXXX 轉換,直接輸出 UTF-8 位元組
控制字元轉義僅轉義 \\ / \n \t \r \b \f " 符合 JSON RFC
關聯/索引陣列判斷鍵為連續整數 0..n-1 視為索引陣列,否則為物件
物件支援stdClass 視為關聯陣列處理
遞歸深度PHP 預設無限制,極深結構可能觸發堆疊溢位

效能與替代方案

  • 手動實作純 PHP 速度較慢(約原生 1/10),資料量 > 10KB 明顯感覺延遲。
  • 建議:若專案仍在 PHP 5.3,**優先升級 PHP** 至 7.4+ 或 8.x,同時獲得效能、安全性、新功能。
  • 若無法升級,可考慮安裝 pecl install jsonc(社群維護的 JSON 擴展)或使用 composer require symfony/polyfill-php54 但該套件不包含 JSON_UNESCAPED_UNICODE polyfill。

驗證測試

<?php
$test = ['中文' => '測試', 'emoji' => '😀', 'nested' => ['a' => 1]];
$json = json_encode_ex($test);
echo $json . "\n";
// {"中文":"測試","emoji":"😀","nested":{"a":1}}

// 反序列化驗證
$back = json_decode($json, true);
assert($back === $test, 'Round-trip 失敗');
echo "Round-trip OK\n";
?>

總結

json_encode_ex() 以 < 50 行代碼解決舊版本 PHP 中文轉義問題,適合無法升級 PHP 的維護專案。新專案請直接使用 PHP 7.4+ 並加上 JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES 獲得最佳體驗。

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