设为首页 收藏本站
查看: 603|回复: 0

[经验分享] php json 乱码

[复制链接]
发表于 2017-3-22 07:24:20 | 显示全部楼层 |阅读模式
  JSON是一种轻量级的数据交换格式,完全语言无关,但是采用了类似于C系列语言的约定,更详细的介绍可以参考:  http://json.org
  由于将数组/对象 序列化为JSON字符串的时候基本上只支持 UTF-8/ASCII, 而我们现在很多网站出于历史原因或者支持国产的原因,采用了GBK/GB2312编码,这个时候,直接使用json_encode/json_decode的时候就可能会出问题了。
  我们从B/S两个方面谈这个问题。
  首先从B(Browser)方面来讲,我们使用JSON作为和S(Server)数据交换的格式,无论如何,S返回的JSON字符串都已经是Unicode的了,由于JavaScript内部采用了Unicode 的编码,JavaScript会根据客户端的编码的不同而自动转化编码,JSON的解析也就不成问题了。比如: 返回的数据是
  "\u4e2d\u56fd\u4eba"

  无论你的页面是GBK,还是UTF-8的,都将可以正确解析为
  “中国人"

  比较简单的方式是调用Javascript的eval函数:
  try{ eval("var ret = " +"\"\u4e2d\u56fd\u4eba\";");} catch(e){}; alert(ret);

  再来看看S(Server)端,json_encode/json_decode会假定给定的数据是UTF-8编码的,这儿就有几种思路了:

  • 将数据转化为UTF-8编码的,然后再调用json_encode, 或者首先json_decode,然后再转化为GBK编码的。
  • 将数据urlencode,这样所有的数据都是ASCII的了,调用json_encode就没有问题了,json_decode之后也需要 urldecode下。
  • 自己编写函数将GBK编码直接转换为unicode代码。
  其实第一种和第二种都是同样的思路,即将其编码转换为可encode的编码,下面看看上面提到的解决方案的具体代码:

encode之前转换为utf-8,decode之后转回gbk:
  function tb_json_encode($value, $options = 0)
{
  return json_encode(tb_json_convert_encoding($value, "GBK", "UTF-8"));
}

function tb_json_decode($str, $assoc = false, $depth = 512)
{
  return tb_json_convert_encoding(json_decode($str, $assoc), "UTF-8", "GBK");
}


function tb_json_convert_encoding($m, $from, $to)
{
  switch(gettype($m)) {
    case 'integer':
    case 'boolean':
    case 'float':
    case 'double':
    case 'NULL':
      return $m;

    case 'string':
      return mb_convert_encoding($m, $to, $from);
    case 'object':
      $vars = array_keys(get_object_vars($m));
      foreach($vars as $key) {
        $m->$key = tb_json_convert_encoding($m->$key, $from ,$to);
      }
      return $m;
    case 'array':
      foreach($m as $k => $v) {
        $m[tb_json_convert_encoding($k, $from, $to)] = tb_json_convert_encoding($v, $from, $to);
      }
      return $m;
    default:
  }
  return $m;
}

  encode之前urlencode,decode之后urldecode:
  function tb_json_encode(array $value, $options = 0) {
  array_walk_recursive($value,'tb_json_encode');
  return $value;
  }
  function tb_json_decode($value, $assoc = false, $depth = 512) {
  array_walk_recursive($value,'tb_json_decode');
  return $value;
  }
  function tb_urlencode(&$value, &$key) {
  $key = urlencode($key);
  $value = urlencode($value);
  }
  function tb_urldecode(&$value, &$key) {
  $key = urldecode($key);
  $value = urldecode($value);
  }

  第三种方式,在这儿就不详细介绍了。
  参考:

  • http://gggeek.altervista.org/sw/article_20061113.html
  • http://json.org
  经过测试发现PHP的递归实现是在是太慢了,于是尝试将地一种方案修改成了使用PHP内置的函数, 相比而言要好很多:
  function tb_json_encode_ex($value, $options = 0)
{
  array_walk_recursive($value, "tb_json_convert_encoding_g2u");
  return json_encode($value);
}
function tb_json_decode_ex($value, $assoc = true, $depth = 512)
{
  $value = json_decode($value);
  array_walk_recursive($value, "tb_json_convert_encoding_u2g");
  return $value;
}
function tb_json_convert_encoding_g2u(&$value, &$key)
{
  $value = mb_convert_encoding($value, "UTF-8", "GBK");
}
function tb_json_convert_encoding_u2g(&$value, &$key)
{
  $value = mb_convert_encoding($value, "GBK", "UTF-8");
}

  事实上,第一种方式有一个优点是和基本的json_decode兼容,而第二种则不行。
  第二种方式还可以有好多"变种",比如使用base64_encode/base64_decode 等等。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-353228-1-1.html 上篇帖子: PHP login Curl 下篇帖子: php水印代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表