V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lcy630409
V2EX  ›  PHP

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

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

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

    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));
    就可以了
    此贴终结,再次感谢各位热心回答,谢谢
    sobigfish
        15
    sobigfish  
       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
    sobigfish
        17
    sobigfish  
       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 啊
    sobigfish
        21
    sobigfish  
       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   ·   实用小工具   ·   5205 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 09:42 · PVG 17:42 · LAX 01:42 · JFK 04:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.