PHP json 编码 - 格式错误的 UTF-8 字符,可能编码不正确

Posted

技术标签:

【中文标题】PHP json 编码 - 格式错误的 UTF-8 字符,可能编码不正确【英文标题】:PHP json encode - Malformed UTF-8 characters, possibly incorrectly encoded 【发布时间】:2018-02-28 12:26:10 【问题描述】:

我在一个数据数组中使用json_encode($data),并且有一个字段包含俄语字符。

我使用这个mb_detect_encoding() 来显示该字段的编码方式,并显示 UTF-8。

我认为 json 编码失败是由于其中的一些错误字符,例如“ра▒”。我在数据上尝试了很多utf8_encode 的东西,它会绕过那个错误,但是数据看起来不再正确了。

如何解决这个问题?

【问题讨论】:

我尝试了很多东西 - 比如什么?请向我们展示您的代码/研究。 你试过JSON_UNESCAPED_UNICODE选项吗? 已经尝试过“JSON_UNESCAPED_UNICODE”。不工作。 我尝试了其他方法,要么会返回相同的错误,要么字符完全改变了一些不可读的东西。 utf8_encode() 用于将 8859-1 转换为 UTF8,输入 UTF8 字符串会损坏它。 【参考方案1】:

如果里面有一些非 utf8 字符,即使其中大部分是 utf8 字符,也会出现问题。这将删除所有非 utf8 字符,现在它可以工作了。

$data['name'] = mb_convert_encoding($data['name'], 'UTF-8', 'UTF-8');

【讨论】:

你可能也想添加这个$mysqli->set_charset("utf8"); 我尝试通过添加以下代码来查找无效字符串:` foreach ($addresses as $address) $converted = mb_convert_encoding($address, 'UTF-8', 'UTF- 8'); if ($converted !== $address) dd($addresses); ` 两点: 1. $converted !== $address 条件永远不会满足。我想这是因为=== 是一个“二进制安全”运算符... 2. 我最终没有得到错误,即使我从未将$converted 分配给任何东西!就像mb_convert_encoding() 通过引用接受字符串一样,虽然它不是……【参考方案2】:

如果您有一个多维数组以 JSON 格式编码,那么您可以使用以下函数:

如果发生 JSON_ERROR_UTF8:

$encoded = json_encode( utf8ize( $responseForJS ) );

以下函数用于对Array数据进行递归编码

/* Use it for json_encode some corrupt UTF-8 chars
 * useful for = malformed utf-8 characters possibly incorrectly encoded by json_encode
 */
function utf8ize( $mixed ) 
    if (is_array($mixed)) 
        foreach ($mixed as $key => $value) 
            $mixed[$key] = utf8ize($value);
        
     elseif (is_string($mixed)) 
        return mb_convert_encoding($mixed, "UTF-8", "UTF-8");
    
    return $mixed;

【讨论】:

mb_convert_encoding 自己进行递归工作,您可以在文档link 中看到:如果 val 是一个数组,则它的所有字符串值都将被递归转换。所以函数utf8ize 是不需要的。您只需要json_encode(mb_convert_encoding($responseForJS, "UTF-8", "UTF-8")); mb_convert_encoding 只有在您运行 php 7.2 或更高版本时才能转换数组,只是为了澄清。否则,此功能完美运行。【参考方案3】:

请确保使用字符集 iso 作为 utf8 启动您的 Pdo 对象。 这应该可以解决这个问题,避免任何重新 utf8izing 的舞蹈。

$pdo = new PDO("mysql:host=localhost;dbname=mybase;charset=utf8", 'user', 'password');

【讨论】:

这解决了我的情况。它也适用于其他连接类型,例如用于 MSSQL Server 的 dlib。 得到了一个旧项目来修复编码问题,这对我帮助很大。唯一的区别是这个项目使用的是 ADO,解决方案有点不同,使用 setCharset() 解决了,这里的信息adodb.org/dokuwiki/…【参考方案4】:

在 php 7.2 中,有两个选项允许在 json_encode 中直接管理无效的 UTF-8:

https://www.php.net/manual/en/function.json-encode

json_encode($text, JSON_INVALID_UTF8_IGNORE);

或者

json_encode($text, JSON_INVALID_UTF8_SUBSTITUTE);

【讨论】:

谢谢,它对我有用,因为我在 api 中的回复在标题字符串中有表情符号,但我有一个困惑,我在某处读到表情符号是 utf-8 字符,那么为什么字符串中的表情符号会给出这个格式错误的 utf-8 字符错误? @HaritsinhGohil 也许有些表情符号是有效的 UTF-8 字符,而另一些则不是......【参考方案5】:

您只需添加您的 pdo 连接 charset=utf8 像下面的 pdo 连接线:

$pdo = new PDO("mysql:host=localhost;dbname=mybase;charset=utf8", 'user', 'password');

希望对你有帮助

【讨论】:

【参考方案6】:

在 JSON 编码之前删除 html 实体。我在PHP中使用html_entity_decode(),问题解决了

$json = html_entity_decode($source);
$data = json_decode($json,true);

【讨论】:

【参考方案7】:

您的结果集中是否有 UUID?在这种情况下,以下数据库标志将有所帮助:

PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER => true

【讨论】:

【参考方案8】:

例如,如果您的数据在数据库中编码良好,请确保在 json_encode 之前使用 mb_ * 函数进行字符串处理。 substr 或 strlen 之类的函数不能很好地与 utf8mb4 配合使用,并且可能会剪切您的文本并留下格式错误的 UTF8

【讨论】:

【参考方案9】:

我知道这是一个古老的话题,但对我来说这是我需要的。我只需要修改答案'jayashan perera'。

//...code
        $stmt->execute();
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);


        for ($i=0; $i < sizeof($result) ; $i++)  
            $tempCnpj = $result[$i]['CNPJ'];
            $tempFornecedor = json_encode(html_entity_decode($result[$i]['Nome_fornecedor']),true) ;
            $tempData = $result[$i]['efetivado_data'];
            $tempNota = $result[$i]['valor_nota'];
            $arrResposta[$i] = ["Status"=>"true", "Cnpj"=>"$tempCnpj", "Fornecedor"=>$tempFornecedor, "Data"=>"$tempData", "Nota"=>"$tempNota" ];
        

        echo json_encode($arrResposta);

我没有使用 .js

obj = JSON.parse(msg); 

【讨论】:

以上是关于PHP json 编码 - 格式错误的 UTF-8 字符,可能编码不正确的主要内容,如果未能解决你的问题,请参考以下文章

json解析常见错误(转载加总结)

php里面怎样把utf-8编码的字符串 (如 \u5e7f), 重新解码成中文,多谢

PHP解决中文乱码问题

反序列化json的坑

php数组转换成json格式后汉字怎么就被解析成字母了啊

把JSON 格式的字符串转换为 PHP数组或对象