json_encode/json_decode 僅支持 UTF-8 編碼字符串。輸入 GBK/GB2312 等非 UTF-8 編碼會導致中文變為 null 或空字符串。
$arr = ['name' => '中文'];
echo json_encode($arr); // {"name":null} 或 {"name":""}
function to_utf8($val) {
if (is_array($val)) {
foreach ($val as $k => $v) $val[$k] = to_utf8($v);
return $val;
}
$encoding = mb_detect_encoding($val, ['ASCII','UTF-8','GBK','GB2312','BIG5']);
return ($encoding && $encoding !== 'UTF-8') ? iconv($encoding, 'UTF-8', $val) : $val;
}
$arr = to_utf8($arr);
echo json_encode($arr); // {"name":"中文"}
function json_encode_chinese($data) {
// 遞歸 urlencode 所有值
array_walk_recursive($data, function(&$v) { $v = urlencode($v); });
$json = json_encode($data);
return urldecode($json);
}
$arr = ['name' => '中文'];
echo json_encode_chinese($arr); // {"name":"中文"}
原理:urlencode 將中文轉為 %E4%B8%AD%E6%96%87(ASCII 安全字符),json_encode 安全處理,最後 urldecode 還原。
echo json_encode($arr, JSON_UNESCAPED_UNICODE); // 直接輸出中文,不轉 \uXXXX
前提:輸入**必須已是 UTF-8**。
JSON.parse() 原生支持 UTF-8。Content-Type: application/json; charset=UTF-8。eval(),安全風險高。function json_encode_safe($data, $options = 0) {
if (PHP_VERSION_ID >= 50400) {
$options |= JSON_UNESCAPED_UNICODE;
}
// 確保輸入 UTF-8
array_walk_recursive($data, function(&$v) {
if (is_string($v)) {
$enc = mb_detect_encoding($v, 'UTF-8, GBK, GB2312, BIG5, ASCII');
if ($enc && $enc !== 'UTF-8') $v = iconv($enc, 'UTF-8', $v);
}
});
return json_encode($data, $options);
}