V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
lcy630409
V2EX  ›  PHP

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

  •  
  •   lcy630409 · Oct 17, 2018 · 8662 views
    This topic created in 2756 days ago, the information mentioned may be changed or developed.

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

    29 replies    2018-10-18 16:16:14 +08:00
    imnpc
        1
    imnpc  
       Oct 17, 2018
    // 过滤掉 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  
       Oct 17, 2018   ❤️ 2
    垃圾 PHP
    PHP 是世界上最垃圾的流行语言
    DamonLin
        3
    DamonLin  
       Oct 17, 2018
    @reus 哈哈哈哈
    lcy630409
        4
    lcy630409  
    OP
       Oct 17, 2018
    @imnpc 不是 emoji 表情呢,那个符号我复制到 v2 保存也不见了,真 tm 蛋痛,用户设置的各类用户名真心无语
    lcy630409
        5
    lcy630409  
    OP
       Oct 17, 2018
    @reus 你这样是会被打的 ^_^
    jowan
        6
    jowan  
       Oct 17, 2018
    数据库设置 utf8mb4 编码,普通的 utf8 只能保存部分 emoji 表情
    jowan
        7
    jowan  
       Oct 17, 2018
    表也要设置一下
    DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    lcy630409
        8
    lcy630409  
    OP
       Oct 17, 2018
    @jowan 不是保存的问题,从微信那边获取过来之后,json_decode 都返回 null,jsonlasterr 为 3,放在解析 json 里 提示这个,开始发现 手动处理了这个用户,然后发现有一小部分用户都有这个问题,就只能找解决办法了
    jowan
        9
    jowan  
       Oct 17, 2018
    @lcy630409 确定不是入库时候无法正确保存的问题吗 另外这个符号能不能贴出来
    wei745359223
        10
    wei745359223  
       Oct 17, 2018
    把 JSON 字符串发出来
    lcy630409
        11
    lcy630409  
    OP
       Oct 17, 2018
    @wei745359223 那个点贴不出来,刚在主题中试过了,保存后 v2 显示不出来,粘贴到百度,回车,然后又跳到百度首页了.....
    koast
        12
    koast  
       Oct 17, 2018 via Android
    不能贴一下字符编码吗
    dobelee
        13
    dobelee  
       Oct 17, 2018
    你确实之前编码是 utf-8 ?
    lcy630409
        14
    lcy630409  
    OP
       Oct 17, 2018
    感谢大家的讨论,找到办法了,问师兄得出了办法了
    在 json_decode 之前
    preg_replace('/[\x00-\x1F\x80-\x9F]/u', '', trim($a));
    就可以了
    此贴终结,再次感谢各位热心回答,谢谢
    run2
        15
    run2  
       Oct 17, 2018
    呃,没有直接测微信的
    $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  
       Oct 17, 2018   ❤️ 1
    run2
        17
    run2  
       Oct 17, 2018
    3 JSON_ERROR_CTRL_CHAR
    lcy630409
        18
    lcy630409  
    OP
       Oct 17, 2018
    @sobigfish 不是你这里面的字符呢,你可以看一下上面的图,在 json 校验下 那个点会被解析成||这个啥符号,粘贴到 notepad++中显示 DC4,估计是啥特殊的表情吧
    yc8332
        19
    yc8332  
       Oct 17, 2018
    人家能发出来你就应该能保存。。没毛病,只是可能你的程序不能支持。。。比如把它转成 unicode 保存,显示的时候再恢复
    sgq1128
        20
    sgq1128  
       Oct 17, 2018
    这是个非法的 json 啊
    run2
        21
    run2  
       Oct 17, 2018
    @lcy630409 #18 16 楼 wei745359223 给你说了,jsonlasterr 3 就是 JSON_ERROR_CTRL_CHAR,这个就是指控制字符,但微信可能并没有传(只是你后期自己测试复制了换行字符类的)
    你可以直接试试微信传过来的,直接 json_decode(mb_convert_encoding())看可以不
    cyspy
        22
    cyspy  
       Oct 17, 2018
    看起来是某种分隔符(小节符号)。无论如何,理论上 JSON 里只能出现 ASCII Escape,其他的都算非法 JSON
    raysonlu
        23
    raysonlu  
       Oct 17, 2018
    微信给用户改昵称的时候不把用户的控制符去掉的么?
    zxq2233
        24
    zxq2233  
       Oct 17, 2018 via Android
    为什么不用 JAVA
    icebay
        25
    icebay  
       Oct 17, 2018
    @zxq2233 #24 这是什么逻辑?
    topzyh
        26
    topzyh  
       Oct 17, 2018
    我遇到过,用 utf8mb4 就行了,如果你用了 TP 之类的框架,框架里也要设置
    jhdxr
        27
    jhdxr  
       Oct 17, 2018   ❤️ 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  
       Oct 18, 2018
    我都 base64 编码加密,然后输出的时候直接解密输出。
    king2014
        29
    king2014  
       Oct 18, 2018
    @mumu 这位说的对
    一般不都是 base64 解决的吗
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   857 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 64ms · UTC 19:10 · PVG 03:10 · LAX 12:10 · JFK 15:10
    ♥ Do have faith in what you're doing.