记一次 scheme 解析参数问题

最近做需求时候, 遇到一个后端联调问题, 需求是 后端A 把一个 json 转成 string 后放到 scheme 的payload参数中, json 如下, text1 是一个字符串,

1
2
3
4
{
"text1": "今天是个好日子",
"trackID1": 123456
}

转换为字符串payload后变成

1
{\"text1\":\"今天是个好日子\",\"trackID1\":123456}

scheme 大致如下:

1
scheme://test/ui/func?p={"hintPayload":"{\"text1\":\"今天是个好日子\",\"trackID1\":123456}","param2":"9"}

然后对 scheme 转义, 下发给客户端, 客户端在解析 scheme 后, 获取各个参数, 然后把payload 字符串给另一个业务后端B.
自测阶段没什么问题, 但是测试发现text1中有换行符以及"时候就不行了, 客户端问题就出在解析 scheme 时候, 会对参数做一次 string 转 json 处理, 这次处理失败了.

报错如下

1
2
3
parse json error(Error Domain=NSCocoaErrorDomain Code=3840 "Unescaped control 
character around line 1, column 42." UserInfo={NSDebugDescription=Unescaped
control character around line 1, column 42., NSJSONSerializationErrorIndex=42}),

意思是text1的第 42 个字符有问题, (注意这里是从 0 开始数的, 但是把有问题的字符串贴到编辑器, 编辑器大多是从 1 开始数的)

客户端 scheme 解析出错

找到有问题的字符是 %0A, 换行符, 嗯, easy, 让 后端A 把 %0A 换成 \\n 下发就好, 经过 scheme 反转义后会变成 \n
很快遇到第二个问题, " 也有问题, 行, 再让 后端A 换成\\"下发, 经过 scheme 反转义后变成\", 客户端终于能解析 scheme 了.

注: iOS 解析 %0A 以及 " 出错, Android 解析 " 出错

后台解析也出错

然后就遇到第三个问题, 当把从 scheme 里面解析出来的payload 给另一个业务 后端B 时候, 转json 就失败了,
第一个问题是 字符串里直接是 \n 后端解析不了,
第二个问题是 \"后端也解析不了
这里尝试客户端做下兼容, \n 换成 \\n, easy,,,
但是 \"处理就麻烦了, payload字符串如下,

1
{     \"text1\": \"今天是个好日子\"有引号\",      \"trackID1\": 123456 }

text1 中有\", 参数 text1/trackID1后面也有\", 直接对字符串处理肯定是不行的
那还得先把 payload 转成 json, 再对其中的值做 \"的转换, 最后再把 json 转成字符串给到后端B.
疯了吧

最后回想下上面,

  1. 后端A 做了两个字符串的处理,
  2. 客户端(iOS / Anrdoid) 两端都也要处理,
  3. 本不该客户端理解的 payload 字段客户端也得做一次 json 化, 然后处理其中的值,
  4. 还有其他字符有问题吗???

怎么看这个思路都有大问题

追溯源头

回到最开始的问题, 客户端居然在 scheme 中的参数解析出了 %0A, 百分号字符是 URL 转义的, 客户端在对 scheme 做了反转义之后, 根本不应该还有 %0A呀? 后端A 下发的 scheme 有问题, 问后端 A scheme 是怎么拼出来的, 答曰: 前端提供的, 直接替换了某些字段, 就转义然后给了客户端.
前端提供的 scheme 如下:

1
scheme://test/ui/func?p={"hintPayload":"{\"text1\":\"text1Value\",\"trackID1\":trackID1Value}","param2":"9"}

后端A 使用上面的 scheme 直接把 text1Value 以及trackID1Value 换成了需要的值, 然后转义下就给了客户端. 所以 text1Value 中的特殊字符根本没有被处理过, 直接一起被转义了, 导致了前面一串的问题.

解决

解决问题总是很无聊的, 后台对 scheme 的处理改为

  1. 使用需要的值, 构造了 json
  2. json 转为字符串
  3. 字符串放在了 scheme 后面的参数中
  4. 转义给了客户端

好像一开始就应该这么做吧? 这反应一个普遍问题, scheme 是前端和客户端的交互的协议, 后端一般不愿意去理解, 最后在实践中也的确没有去理解, 直接通过字符串替换的方式完成了需求, 最后导致了联调问题.

-------------本文结束感谢您的阅读-------------

欢迎关注我的其它发布渠道