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

为何json_encode返回空字符串?PHP嵌套数组转JSON遇UTF-8编码问题

解决PHP嵌套数组json_encode返回JSON_ERROR_UTF8的问题

问题描述

有一个3层嵌套的普通PHP数组,通过两层循环构建,未使用特殊对象,var_dump输出结构如下:

array (size=2)
  'tram B' => 
    array (size=2)
      0 => 
        array (size=3)
          'name' => string 'Ile Verte' (length=9)
          'distance' => int 298
          'stationID' => int 762
      1 => 
        array (size=3)
          'name' => string 'La Tronche Hôpital' (length=18)
          'distance' => int 425
          'stationID' => int 771
  16 => 
    array (size=4)
      0 => 
        array (size=3)
          'name' => string 'Bastille' (length=8)
          'distance' => int 531
          'stationID' => int 397
      1 => 
        array (size=3)
          'name' => string 'Xavier Jouvin' (length=13)
          'distance' => int 589
          'stationID' => int 438

其他同结构数组能正常json_encode,但该数组编码失败。排查发现:当mb_detect_encoding返回ASCII时编码正常,返回UTF-8则失效;json_last_error()返回JSON_ERROR_UTF8,说明存在格式错误的UTF-8字符。

原因分析

JSON规范要求所有字符串必须是有效UTF-8编码,出现JSON_ERROR_UTF8通常是两种情况:

  • 字符串实际是其他编码(比如ISO-8859-1、GBK),却被当作UTF-8处理
  • UTF-8字符串存在截断、字节损坏的情况(比如读取文件时未完整获取)
    从数组里的La Tronche Hôpital包含特殊字符ô来看,很大概率是这类特殊字符的编码格式不规范导致的。

解决办法

1. 递归修复数组所有字符串的UTF-8编码

写一个递归函数遍历数组,把所有字符串转成标准UTF-8,同时过滤无效字节:

function fixUtf8($data) {
    if (is_array($data)) {
        foreach ($data as $k => $v) {
            $data[$k] = fixUtf8($v);
        }
        return $data;
    } elseif (is_string($data)) {
        // 先尝试从ISO-8859-1转UTF-8,失败则清理无效字符
        $fixed = mb_convert_encoding($data, 'UTF-8', 'ISO-8859-1');
        if (!$fixed) {
            $fixed = preg_replace('/[\x00-\x1F\x7F-\xFF]/u', '', $data);
        }
        return $fixed;
    }
    return $data;
}

// 修复后再转JSON
$fixedArr = fixUtf8($originalArr);
$json = json_encode($fixedArr);

2. 强制生成JSON(适合临时调试)

如果想保留尽可能多的数据,可以用JSON_PARTIAL_OUTPUT_ON_ERROR参数跳过错误字符,配合JSON_UNESCAPED_UNICODE保留原字符:

$json = json_encode($originalArr, JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR);

注意:这个方法会丢失错误字符,不建议生产环境使用。

3. 从源头修正编码

如果数组来自数据库、文件或外部接口,先确认数据源编码:

  • 从MySQL读取时,设置连接编码为utf8mb4:
    mysqli_set_charset($dbConn, 'utf8mb4');
    
  • 读取文件时,指定正确的源编码转成UTF-8:
    $content = file_get_contents('data.txt');
    // 假设源文件是ISO-8859-1,根据实际情况调整
    $content = mb_convert_encoding($content, 'UTF-8', 'ISO-8859-1');
    

验证修复结果

修复后可以用以下代码确认:

// 检查特殊字符的编码
echo mb_detect_encoding($fixedArr['tram B'][1]['name'], 'UTF-8,ISO-8859-1', true);
// 确认JSON编码是否成功
$json = json_encode($fixedArr);
if ($json === false) {
    echo json_last_error_msg();
} else {
    echo $json;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 16:05:05