美文网首页
从一个字符串看出json_encode的有无

从一个字符串看出json_encode的有无

作者: 舒小贱 | 来源:发表于2017-09-21 18:32 被阅读0次

    今天解决客户现场的一个bug发现了此问题。先直接抛出两个json_encode后的字符串:

    $str = '{"detail":{"base_config":{"ping_time":{"value":"60","inherit":"0","global":"0"},"net_env":{"value":"2","inherit":"0","global":"1"},"lib_update":{"value":"2","inherit":"0","global":"1"},"leak_update":{"value":"2","inherit":"0","global":"1"},"net_protocol":{"value":"1.0","inherit":"0","global":"0"}},"sd":{"sd_settings":{"sysfix":{"value":"2","inherit":"0","global":"1"},"compensate":{"value":"0","inherit":"0"},"bd_scan":{"value":"0"},"bd_moniter":{"value":"0"}}},"safe_control_list":{"list":[{"gid":"765","gname":"upanceshi","isactive":"1","time_range":"\u6240\u6709\u65f6\u95f4","time_range_id":"1","policy_tpl":"usb\u901a\u7528","policy_tpl_id":"14","isonline":"3","priority":"1"}]},"client_attribute":{"is_virtual":"0","cvm":""}},"gid":765,"client_type":0,"tpl_id":null,"id":164,"type":0}';
    
    $str1 = '{"id":7,"tpl_id":null,"detail":"{\"dsec_devexclude\":{\"type\":\"set_movedevice_exclude\"},\"dsec_newudisk\":{\"type\":\"set_udisk_auth\",\"auth_stop_flag\":\"0\",\"auth_stop_tips\":\"\",\"auth_read_flag\":\"0\",\"auth_read_tips\":\"\",\"auth_readwrite_flag\":\"0\",\"auth_readwrite_tips\":\"\",\"param\":[{\"device_id\":\"000000000000000000\",\"authtype\":\"3\",\"todate\":\"\",\"pid\":\"\",\"vid\":\"\",\"security_level\":\"1\"}]},\"systeminfo\":{\"independent\":\"1\",\"pcname\":\"\",\"mode\":\"0\"},\"safe_control_list\":{\"list\":[]},\"audit_control_list\":{\"list\":[]}}","create_user":null,"update_user":null,"type":0,"gid":84,"tags":null,"start_ip":null,"end_ip":null,"update_time":"2016-05-31 00:37:11.481749","create_time":"2016-05-31 00:37:11.481749","start_time":"2016-05-31 00:00:00","name":null,"client_type":0}';
    

    你发现了这两个字符串有什么不一样吗,这两个不一样跟json_encode有什么区别吗
    你发现了第二个字符串,detail里面的*那些引号前面都有*吗,为什么会这样??因为第二个字符串里面,detail经过了一次单独的json_encode,然后才把整个数组再次json_encode,第二次json_encode的时候,就把第一次json_encode得到的字符串里面的引号前面加上了\。
    实例验证:

    $de1 = json_decode($str, true);
    var_dump($de1["detail"]);
    var_dump("111\n");
    $de2 = json_decode($de1["detail"], true);
    var_dump($de2);
    

    输出结果为:

     ...
        ["is_virtual"]=>
        string(1) "0"
        ["cvm"]=>
        string(0) ""
      }
    }
    string(4) "111"
    PHP Warning:  json_decode() expects parameter 1 to be string, array given in D:\Program Files (x86)\360\skylar6\php\3.php
    Warning: json_decode() expects parameter 1 to be string, array given in D:\Program Files (x86)\360\skylar6\php\3.php on l
    NULL
    D:\Program Files (x86)\360\skylar6\php>
    

    看到没:$str是进过一次json_encode形成的,把$str进行两次json_decode就会出错。
    再验证一下$str1:

    $de1 = json_decode($str1, true);
    var_dump($de1["detail"]);
    var_dump("111\n");
    $de2 = json_decode($de1["detail"], true);
    var_dump($de2);
    

    结果为:

        string(1) "0"
      }
      ["safe_control_list"]=>
      array(1) {
        ["list"]=>
        array(0) {
        }
      }
      ["audit_control_list"]=>
      array(1) {
        ["list"]=>
        array(0) {
        }
      }
    }
    
    D:\Program Files (x86)\360\skylar6\php>
    

    没有问题。

    问题背景:客户现场多个分组,
    (1)绝大部分分组是通过testrunCommand定时任务刷入到redis里面的,刷入逻辑为:
    先将$policy["detail"]单独json_encode一次,然后再将整个$policy进行一次json_encode。(此时得到的应该是$str1)
    (2)某几个分组是通过另外的接口刷入到redis里面的,刷入逻辑为:直接将整个$policy进行json_encode一次(此时得到的应该是$str)。

    以上两种消费者,不同的操作,用的是同一个消费者:消费者先对¥str进行一次json_decode,得到$policy,然后将$policy["detail"]再次json_decode一次。

    那么问题来了:
    那几个分组进行第一次json_decode后,得到的$policy["detail"]就是一个数组,而不是一个字符串,那么对数组进行json_decode当然会出问题啊。所以bug就这样来了。

    其实问题不是很难,但是比较难排查的原因是,消费逻辑是php-cgi异步消费的,并没有记录日志。。。前人埋坑,后人跳。。。

    相关文章

      网友评论

          本文标题:从一个字符串看出json_encode的有无

          本文链接:https://www.haomeiwen.com/subject/ibktextx.html