You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决json_encode因未知字符失败的问题——USSD响应文本乱码导致JSON序列化失败

解决USSD响应乱码导致json_encode失败的问题

这个问题我之前处理过不少——本质就是USSD响应的编码和PHP默认的UTF-8不兼容导致的乱码,进而卡壳了json_encode。咱们一步步来解决:

核心原因

USSD协议的文本通常采用GSM 03.38编码(俗称GSM字符集),而PHP默认的字符串处理是基于UTF-8的。当你直接读取USSD响应时,那些GSM特有的字符(比如特殊问号、控制字符)会被解析成无效的UTF-8字节,也就是你看到的��乱码,而json_encode对非UTF-8的字符串会直接编码失败。

具体解决步骤

1. 把GSM编码字符串转成UTF-8

这是最关键的一步,你可以用PHP的mb_convert_encoding或者iconv函数来完成转换:

方法一:用mb_convert_encoding

// 从数组中取出乱码的text字段
$rawText = $responses[0]['text'];
// 从GSM 03.38转成UTF-8
$utf8Text = mb_convert_encoding($rawText, 'UTF-8', 'GSM-03.38');

如果你的PHP环境不识别GSM-03.38这个编码名,试试简写GSM。

方法二:用iconv(带错误忽略)

如果mb_convert_encoding转换失败,可以用iconv并加上//IGNORE参数,忽略无法转换的无效字符:

$utf8Text = iconv('GSM-03.38', 'UTF-8//IGNORE', $rawText);

2. 清理残留的无效字符

转换后可能还会残留一些USSD里的控制字符、多余符号(比如你看到的%),可以用正则过滤掉非打印的UTF-8字符,只保留正常的文本内容:

// 保留字母、数字、标点、空格,去掉其他无效字符
$cleanText = preg_replace('/[^\p{L}\p{N}\p{P}\p{Z}]/u', '', $utf8Text);

如果你需要保留Yes 2 No, CANCEL, SEND这些选项内容,这个正则不会影响它们。

3. 验证并执行json_encode

最后确认转换后的字符串是有效的UTF-8,再执行编码:

if (mb_check_encoding($cleanText, 'UTF-8')) {
    $result = json_encode(['responses' => [['date' => $responses[0]['date'], 'text' => $cleanText]]]);
    // 现在应该能正常生成JSON了
} else {
    // 处理极端情况:修复无效的UTF-8字节
    $cleanText = mb_convert_encoding($cleanText, 'UTF-8', 'UTF-8');
    $result = json_encode(['responses' => [['date' => $responses[0]['date'], 'text' => $cleanText]]]);
}

额外提示

如果尝试GSM编码转换后还是有问题,可能你的USSD响应采用了其他编码(比如ISO-8859-1),可以用mb_detect_encoding尝试检测原编码,但注意这个函数的准确性有限,优先还是用GSM 03.38测试。

内容的提问来源于stack exchange,提问作者Alaa Morad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 21:48:11