PHP字符编码(UTF-8/GBK)与json_encode/json_decode的关系
发布日期:2021-10-05 13:28:30 浏览次数:2 分类:技术文章

本文共 3060 字,大约阅读时间需要 10 分钟。

  在项目中,因为字符编码的问题,踩了不少坑,之前踩,现在还接着踩,现在把它们总结出来,只希望以后不要再踩这坑了,我把我踩过的坑总结一下:

  1)将数组转成json数据,json数据为null或为空字符串;
  2)将数组转成json数据,json中的汉字乱码;
  3)当json数据嵌套时(数组是个json,数组中的某个字段,也是个json字符串),json_decode失败;

1 基本概念

  Unicode:(统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。
  UTF-8:是一种针对Unicode的可变长度字符编码,又称万国码,UTF-8用1到4个字节编码Unicode字符。
  GBK:汉字编码字符集。 
  json_encode:PHP中将数组转成json数据,只支持utf8格式的数据;
  json_decode:PHP中将json数据转换成数组,转换后的数组是utf8格式;

2 UTF-8/GBK与json_encode

  情况1:GBK–>UTF-8–>json_encode
  代码如下:

$strTest = '测试用例';$strConvet = iconv('GBK', 'UTF-8', $strTest);var_dump($strConvet);$strJson = json_encode($strConvet);var_dump($strJson);

  这里需要分两种情况讨论,当数据$strTest为gbk格式,输出结果:

string(12) "测试用例"string(26) ""\u6d4b\u8bd5\u7528\u4f8b""

  这里没有问题,数据是从gbk–>utf8–>json_encode,流程完全正确(说明一下,”\u6d4b\u8bd5\u7528\u4f8b”是unicode格式,也就是php进行json_encode时,会自动将utf8格式的汉字转为unicode格式,除汉字以外,其它的还是按照utf8格式输出,专门将汉字转为unicode,这样其实有个很大的好处,后面会讲)。

  如果数据$strTest为utf8格式,输出结果:

string(18) "娴嬭瘯鐢ㄤ緥"string(38) ""\u5a34\u5b2d\u762f\u9422\u3124\u7de5""

  出现乱码了!!!数据是从utf8->utf8–>json_encode,也就是数据$strTest为utf8格式,然后把按照gbk的方式强转为utf8,就出现乱码了,虽然是乱码,但这些乱码仍然是utf8格式,所以json_encode后,仍然会有输出结果。

  情况2:UTF-8–>GBK–>json_encode
  代码如下:

$strTest = '测试用例';$strConvet = iconv('UTF-8', 'GBK', $strTest);var_dump($strConvet);$strJson = json_encode($strConvet);var_dump($strJson);

  同上,这里也需要分两种情况讨论,当数据$strTest为utf8格式,输出结果:

string(8) "测试用例"string(4) "null"

  没有出现乱码,但是json_encode后的数据为null!!!数据是从utf8–>gbk–>json_encode,因为json_encode只接受utf8格式的数据,gbk的数据不能直接转成json,只会输出null。

  如果数据$strTest为utf8格式,输出结果:

string(0) ""string(2) """"

  啥都没有了!!!数据是从gbk->gbk–>json_encode,也就是将utf8格式的数据,按照utf8的方式强转为gbk,直接转成空字符串。然后空的字符串json_encode后还是空字符串。(可能你会说,这个空字符串是gbk格式的啊,按照上面说的,json_encode后应该是null,我试了一下,英文字符是不区分utf8个gbk格式的,不管怎么转,输出的还是英文字符)

  通过上面的2种情况,准确来说是4种情况,就基本知道为什么转码后,会出现各种各样的问题,总结一下,其实就是没有按照标准去使用转码函数。

3 UTF-8/GBK与json_decode

  其实核心的东西,上面都已经讲了,只是json_decode的入参也必须是utf8格式的,只要保证这一点,json_decode后的数据就不会存在问题,但是在项目中,经过多次转码后,就不能保证json_decode的入参是utf8格式了,很容易出现乱码,我举个项目中遇到的例子。
  项目示例:调用第三方的接口,会吐给我一个json串,这个json串是个数组,然后数组中有一个字段也是个json串,更恐怖的时,这个json串中的汉字居然不是unicode格式,而是个纯粹的utf8格式,示例数据如下:

{"ret":0,"msg":"OK","content":{"user_name":"","true_name":"{\"materialType\":\"测试数据类型\",\"materialFormat\":\"image\"}"}}

  json_decode后的数据:

{    "ret": 0,    "msg": "OK",    "content": {        "user_name": "",        "true_name": "{\"materialType\":\"测试数据类型\",\"materialFormat\":\"image\"}"    }}

  因为项目中,我们这边处理数据的格式是GBK,所以第三方的数据会马上转成GBK格式,但是后续如果需要用到字段true_name中的数据materialType,需要将true_name单独json_decode,因为之前我们已经将其转为gbk格式,所以这里使用json_decode肯定会出现问题(这就是为什么json数据中的汉字,一般会转为unicode,如果汉字为unicode,就不会出现上述问题了)。为了解决这个问题,我们是先将第三方给我们的json数据,先转成数组,然后单独对字段true_name进行json_decode,这样所有字段就不存在json数据了,再统一将所有数据转成GBK格式。

  最后补充一点,json_encode方法会自动将汉字转成unicode格式,如果因为一些特殊要求,需要将将里面的汉字保留为utf8格式(一般不要这样,会给自己埋坑,我指的是因为特殊要求,不得已才这么处理),使用方法如下:

json_encode($arrInput, 'GBK', 'UTF-8'), JSON_UNESCAPED_UNICODE)

  但是这里又有个坑,看一下php帮助文档:

  这里写图片描述
  这个参数JSON_UNESCAPED_UNICODE,只有php5.4.0以上的版本(包括5.4.0)才能使用,如果你线下机器是php5.4.0,线上机器是php5.4.0一下版本,这个坑估计会被踩的很冤!

总结:这些坑是我一路踩过来的,估计以后还会有坑,不过我想应该不会很多了,如果还会踩到其它坑,会在该片博文中补充。

转载地址:https://blog.csdn.net/lml200701158/article/details/52663046 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:C盘瘦身
下一篇:PHP源码安装

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月25日 15时53分54秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章