哎,我真的服了!今天调代码又踩到这个坑了,气得我差点把键盘给扔了。你们有没有遇到过这种状况——在PHP里,明明一个好好的数组,里面带着中文,比如['name' => '张三', 'city' => '北京'],一用json_encode扔出去,到前端一看,傻眼了:{"name":"\u5f20\u4e09","city":"\u5317\u4e2a"}。全是这种\u开头的鬼画符!
前端同事又来找我了:“哥,你这接口返回的啥啊,看不懂啊!” 我也很无奈啊兄弟,这又不是我干的,是PHP它自己“热情过度”帮我们转义了!
其实这个问题说穿了,就是json_encode这个函数,默认情况下,为了保护数据,会把非ASCII字符(包括中文)转换成Unicode转义序列。本意是好的,但在咱们大中文环境下,经常是帮倒忙,让数据可读性变得极差,有时候还会导致一些解析上的小麻烦。
不废话了,直接上解决方案!亲测有效,任君挑选。
第一招:简单粗暴,直接加参数
这是最常用的办法。json_encode其实有第二个参数,可以指定一些选项。对付中文乱码,咱们请出JSON_UNESCAPED_UNICODE这个神器。
$data = ['name' => '张三', 'city' => '北京'];
echo json_encode($data, JSON_UNESCAPED_UNICODE);就这么简单!输出瞬间变得清爽:{"name":"张三","city":"北京"}。这个选项的意思就是“不要编码Unicode字符”。百分之九十的情况,用这招就妥了。
第二招:从源头搞定,统一字符集
有时候问题不在JSON,而在源头。你PHP文件本身的编码、数据库的编码、甚至Apache/Nginx的配置,如果乱七八糟,比如文件是UTF-8,但数据库连接是GBK,那怎么折腾json_encode都没用,出来的可能就是真正的乱码(比如???或者�)。
所以,养成好习惯:
1、PHP文件本身保存为UTF-8 without BOM格式(用Notepad++或VS Code都能轻松设置)。
2、在代码开头,或者框架的入口文件,明确定义一下头部和内部编码:
header('Content-Type: application/json; charset=utf-8');
mb_internal_encoding('UTF-8');3、确保你的数据库连接也设置了UTF-8。比如MySQLi:
$mysqli->set_charset('utf8mb4');第三招:曲线救国,先转后拼(适用于老旧环境)
如果你碰到了一个超级老旧的PHP环境(比如5.2以下,天啊现在还有吗?),不支持JSON_UNESCAPED_UNICODE常量怎么办?别急,还有办法。
我们可以先把中文部分URL编码一下,json_encode之后,再解码回来。有点绕,但管用。
$data = ['name' => '张三', 'city' => '北京'];// 先编码数组中的中文字符串
array_walk_recursive($data, function (&$item) {
if (is_string($item)) {
$item = urlencode($item);
}});
// 正常转JSON$json = json_encode($data);// 再把JSON字符串里的编码还原
$json = urldecode($json);
echo $json;这方法就像先把宝贝装进保险箱(URL编码),过安检(json_encode),到了地方再开箱(URL解码)。虽然步骤多了点,但胜在兼容性无敌。
最后唠两句
我自己平时无脑用第一招,加个JSON_UNESCAPED_UNICODE参数,干净利落。记住啊,编码问题在PHP开发里就像鞋子里的沙子,不大但烦人。养成良好的编码环境统一习惯(UTF-8万岁!),能省下后面无数扯皮的功夫。
希望下次你再看到\u5f20\u4e09的时候,能会心一笑,然后淡定地把它干掉。如果还有啥奇葩情况,欢迎留言吐槽,咱们一起研究!