收藏
回答

关于JSON解析时 Unicode U+2028 等字符的bug

框架类型 问题类型 API/组件名称 终端类型 微信版本 基础库版本
小程序 Bug wx.request 客户端 6.7.3 2.4.0

- 概述


wx.request 对于含有 U+2028 等字符的 Response Body 存在错误的过度处理(注意:该问题只在真机上复现)。


经过查找文章和社区,我发现这是一个反馈较多的问题(参见最后“可能的相关问题”部分),对于特殊字符很多人选择了进行过滤,但这是不对的,正确的做法应当是对其进行合理编码、解码。


- JSON对特殊字符的处理


在详细描述bug之前,我们先了解下JSON处理中特殊字符的正确处理方式。


在 ECMAscript 5.1 ( https://www.ecma-international.org/ecma-262/5.1/#sec-15.12.2 ) 中有这样一句话:


JSON uses a more limited set of white space characters than WhiteSpace and allows Unicode code points U+2028 and U+2029 to directly appear in JSONString literals without using an escape sequence.


这意味着 JSON.stringify 和 JSON.parse 都不应当对空格、U+2028、U+2029这三个字符进行转义,例如对于空格:



可以看到空格未进行转义,同样的道理,U+2028 也不会被转义:




但对于 '\n' ,是需要转义的:




因此可以得出结论,在HTTP Response中 U+2028 等字符是不应当被转义的;由于这两个字符被创造也是有其含义和目的,更不应当被过滤掉(如 https://developers.weixin.qq.com/community/develop/doc/8d93389c3bea4acff6e7bb765c3e634f?highLine=2028https://developers.weixin.qq.com/community/develop/doc/f085c4b5f547113dbb032d0f4b46e1b5


- wx.request 的问题


在 wx.request 对JSON的处理中,没有正确将 JSON String 解析为 Object,而是将 String进行了返回,同时将 U+2028 和 U+2029 两个字符替代成了 \n 。在这一过程中存在如下问题:


  1. 假设wx.request处理JSON异常,应当触发fail回调函数传递具体的错误,给用户明确的意图,而不是调用 success 给出未能成功解析的字符串。(举一个例子,JSON.parse 结果并不一定是Object,如 http://www.mocky.io/v2/5bea7d792f0000df0bda3a4e 这个接口在浏览器用fetch调用返回的就是字符串)。

  2. wx.request应当能正常处理含有U+2028 等字符的Response,应当原样保留这些特殊字符并反馈 JSON.parse 出的结果

  3. 但是通过调试可以发现,wx.request对U+2028 等字符进行了错误的处理,在返回的 String 中将其替换成了 \n (注意不是 \\n,前者是一个字符,后者是两个字符),这进一步导致了用户难以通过 JSON.parse 手动解析String数据:




在上面的例子中我说过 '\n' 是应该被转义为 '\\n' 的,否则在 JSON.parse 的时候就会造成报错。


- 预期表现


  1. wx.reqeust应该正确处理特殊字符

  2. wx.request在JSON解析失败时应当调用fail回调


- 临时解决方案


这是一个会有bug的解决方案,原因不再赘述,仅供参考:


wx.request({
  url: "http://xxx",
  success(res) {

    const originData = res.data;

   // 无法处理纯字符串的情况,慎用

    const data =
      typeof originData === "string"
        ? JSON.parse(originData.replace(/\n/g, "\\n"))
        : originData;
    console.log(data); // 替代 res.data
  }
});


- 复现路径


在这个代码片段中 https://developers.weixin.qq.com/s/iam8hTmP7m3S ,可以通过点击不同button分别调用含有 \n 、\u2028、\u2029 和空格的接口,查看console的输出。


注意:必须在真机上才能复现,模拟器不可以


- 可能的相关问题


https://developers.weixin.qq.com/community/develop/doc/8d93389c3bea4acff6e7bb765c3e634f?highLine=2028

https://developers.weixin.qq.com/community/develop/doc/000ca414b64b1099bb1701ce55b800?highLine=2028

https://developers.weixin.qq.com/community/develop/doc/99f032bff8b2a6ccb37ffd4414aa5575?highLine=json%25202028

https://developers.weixin.qq.com/community/develop/doc/000c443ed5c488009dd6b81aa51404?highLine=2028

https://developers.weixin.qq.com/community/develop/doc/f085c4b5f547113dbb032d0f4b46e1b5

https://developers.weixin.qq.com/community/develop/doc/ca057a276c3e316cb5086b0b26a69763


此外这个问题反馈了U+2028与setData使用的bug,我猜测可能与本问题可能存在一定的关联性:

https://developers.weixin.qq.com/community/develop/doc/000c443ed5c488009dd6b81aa51404?highLine=2028

最后一次编辑于  2018-11-13
回答关注问题邀请回答
收藏

7 个回答

  • 蒋欢
    蒋欢
    2020-12-14

    现在 ios12 wechat 7.0.14 还有这个问题,ios 14 wechat 7.0.18 没这个问题了

    2020-12-14
    有用
    回复
  • 泡沫
    泡沫
    2020-07-17

    现在 android 上没有问题,ios 有问题

    2020-07-17
    有用
    回复
  • 李大树
    李大树
    2020-07-03

    请问官方还跟进嘛?

    2020-07-03
    有用
    回复
  • Malash
    Malash
    2019-11-14

    请问这个问题官方可以继续跟进下吗?

    2019-11-14
    有用
    回复
  • Hasaki
    Hasaki
    2019-07-16

    chrome里可以,小程序不行。


    这些不被支持的字符,我们目前靠在输入和更新数据源的时候做字符替换来解决。


    但是,要是官老爷看见了要要优化的话,我第一个表示支持哦!



    ☺️

    2019-07-16
    有用
    回复
  • waiter
    waiter
    2019-07-15

    +1,表支持

    2019-07-15
    有用
    回复
  • 城主
    城主
    2019-02-26

    哎,这么多反馈的,腾讯就是视而不见

    2019-02-26
    有用
    回复
登录 后发表内容