PHP 解析微信用户信息昵称中有特殊字符,一个点, json 无法解析 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lcy630409
V2EX    PHP

PHP 解析微信用户信息昵称中有特殊字符,一个点, json 无法解析

  •  
  •   lcy630409 2018-10-17 09:45:44 +08:00 8422 次点击
    这是一个创建于 2582 天前的主题,其中的信息可能已经有所发展或是发生改变。

    http://file.whzxc.cn/126.png 如图,获取微信用户信息中的昵称,这个点,php json 解析不了,复制到百度 百度都直接跳到首页了 使用 mb_convert_encoding(,'utf-8','utf-') 也不行 谁知道怎么过滤么

    29 条回复    2018-10-18 16:16:14 +08:00
    imnpc
        1
    imnpc  
       2018-10-17 09:52:29 +08:00
    // 过滤掉 emoji 表情
    function filterEmoji($str)
    {
    $str = preg_replace_callback( '/./u',
    function (array $match) {
    return strlen($match[0]) >= 4 ? '' : $match[0];
    },
    $str);
    return $str;
    }
    reus
        2
    reus  
       2018-10-17 10:09:46 +08:00   2
    垃圾 PHP
    PHP 是世界上最垃圾的流行语言
    DamonLin
        3
    DamonLin  
       2018-10-17 10:11:43 +08:00
    @reus 哈哈哈哈
    lcy630409
        4
    lcy630409  
    OP
       2018-10-17 10:13:39 +08:00
    @imnpc 不是 emoji 表情呢,那个符号我复制到 v2 保存也不见了,真 tm 蛋痛,用户设置的各类用户名真心无语
    lcy630409
        5
    lcy630409  
    OP
       2018-10-17 10:13:58 +08:00
    @reus 你这样是会被打的 ^_^
    jowan
        6
    jowan  
       2018-10-17 10:16:17 +08:00
    数据库设置 utf8mb4 编码,普通的 utf8 只能保存部分 emoji 表情
    jowan
        7
    jowan  
       2018-10-17 10:17:30 +08:00
    表也要设置一下
    DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    lcy630409
        8
    lcy630409  
    OP
       2018-10-17 10:19:37 +08:00
    @jowan 不是保存的问题,从微信那边获取过来之后,json_decode 都返回 null,jsonlasterr 为 3,放在解析 json 里 提示这个,开始发现 手动处理了这个用户,然后发现有一小部分用户都有这个问题,就只能找解决办法了
    jowan
        9
    jowan  
       2018-10-17 10:21:16 +08:00
    @lcy630409 确定不是入库时候无法正确保存的问题吗 另外这个符号能不能贴出来
    wei745359223
        10
    wei745359223  
       2018-10-17 10:26:46 +08:00
    把 JSON 字符串发出来
    lcy630409
        11
    lcy630409  
    OP
       2018-10-17 10:30:01 +08:00
    @wei745359223 那个点贴不出来,刚在主题中试过了,保存后 v2 显示不出来,粘贴到百度,回车,然后又跳到百度首页了.....
    koast
        12
    koast  
       2018-10-17 10:32:40 +08:00 via Android
    不能贴一下字符编码吗
    dobelee
        13
    dobelee  
       2018-10-17 10:43:51 +08:00
    你确实之前编码是 utf-8 ?
    lcy630409
        14
    lcy630409  
    OP
       2018-10-17 10:44:43 +08:00
    感谢大家的讨论,找到办法了,问师兄得出了办法了
    在 json_decode 之前
    preg_replace('/[\x00-\x1F\x80-\x9F]/u', '', trim($a));
    就可以了
    此贴终结,再次感谢各位热心回答,谢谢
    run2
        15
    run2  
       2018-10-17 10:45:39 +08:00
    呃,没有直接测微信的
    $jstring= '{"nickname":"喜喜(●ˇˇ●)","sex":2}';
    var_dump(mb_convert_encoding($jstring,'utf-8'));
    var_dump(json_decode(mb_convert_encoding($jstring,'utf-8')));
    var_dump(json_last_error_msg());
    但没毛病啊,你 php 版本?


    Output for 5.6.38 - 7.3.0rc3
    string(48) "{"nickname":"喜喜(●ˇˇ●)","sex":2}"
    object(stdClass)#1 (2) {
    ["nickname"]=>
    string(25) "喜喜(●ˇˇ●)"
    ["sex"]=>
    int(2)
    }
    string(8) "No error"
    wei745359223
        16
    wei745359223  
       2018-10-17 10:46:38 +08:00   1
    run2
        17
    run2  
       2018-10-17 10:52:25 +08:00
    3 JSON_ERROR_CTRL_CHAR
    lcy630409
        18
    lcy630409  
    OP
       2018-10-17 13:51:14 +08:00
    @sobigfish 不是你这里面的字符呢,你可以看一下上面的图,在 json 校验下 那个点会被解析成||这个啥符号,粘贴到 notepad++中显示 DC4,估计是啥特殊的表情吧
    yc8332
        19
    yc8332  
       2018-10-17 13:54:19 +08:00
    人家能发出来你就应该能保存。。没毛病,只是可能你的程序不能支持。。。比如把它转成 unicode 保存,显示的时候再恢复
    sgq1128
        20
    sgq1128  
       2018-10-17 14:01:08 +08:00
    这是个非法的 json 啊
    run2
        21
    run2  
       2018-10-17 14:01:31 +08:00
    @lcy630409 #18 16 楼 wei745359223 给你说了,jsonlasterr 3 就是 JSON_ERROR_CTRL_CHAR,这个就是指控制字符,但微信可能并没有传(只是你后期自己测试复制了换行字符类的)
    你可以直接试试微信传过来的,直接 json_decode(mb_convert_encoding())看可以不
    cyspy
        22
    cyspy  
       2018-10-17 16:02:54 +08:00
    看起来是某种分隔符(小节符号)。无论如何,理论上 JSON 里只能出现 ASCII Escape,其他的都算非法 JSON
    raysonlu
        23
    raysonlu  
       2018-10-17 16:49:17 +08:00
    微信给用户改昵称的时候不把用户的控制符去掉的么?
    zxq2233
        24
    zxq2233  
       2018-10-17 18:38:40 +08:00 via Android
    为什么不用 JAVA
    icebay
        25
    icebay  
       2018-10-17 18:51:48 +08:00
    @zxq2233 #24 这是什么逻辑?
    topzyh
        26
    topzyh  
       2018-10-17 22:57:34 +08:00
    我遇到过,用 utf8mb4 就行了,如果你用了 TP 之类的框架,框架里也要设置
    jhdxr
        27
    jhdxr  
       2018-10-17 23:35:55 +08:00   5
    先上一个能复现的代码:
    ```
    <?php

    $str = '"'.chr(11).'"';

    var_dump(json_decode($str), json_last_error(), json_last_error_msg());
    ```

    但这个并不是 php 的实现问题,实际上如果你在 js 中(我只在 firefox56 中进行了测试)
    ```
    JSON.parse('"\x0b"');
    ```
    实际上你也会得到类似的出错信息:SyntaxError: JSON.parse: bad control character in string literal at line 1 column 2 of the JSON data


    原因是什么呢?如果你查看 json 的定义( http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf ),其中对于 string 做了明确的定义:
    A string is a sequence of Unicode code points wrapped with quotation marks (U+0022). All code points may be placed within the quotation marks except for the code points that must be escaped: quotation mark (U+0022), reverse solidus (U+005C), and the control characters U+0000 to U+001F.

    注意其中非常明确指出了控制符(\x00-\x1f )需要被转义,否则这就是一个非法的 json。所以在这种情况下只能说微信不负责任的给了一个非法的 json,@lcy630409 在 14 楼的代码就可以算是一个解决方案(直接过滤掉无效字符)


    @reus 不了解真相的开喷,只能说明你自己是。。。


    @raysonlu 早期微信的确没有过滤控制字符。然后通过这些字符(比如\u202e )在一些时候(比如撤回消息)时会出现一些神奇的效果。当然现在已经在改名时过滤了。但之前改的那些依然有效。
    mumu
        28
    mumu  
       2018-10-18 15:32:43 +08:00
    我都 base64 编码加密,然后输出的时候直接解密输出。
    king2014
        29
    king2014  
       2018-10-18 16:16:14 +08:00
    @mumu 这位说的对
    一般不都是 base64 解决的吗
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5166 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 09:07 PVG 17:07 LAX 01:07 JFK 04:07
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86