在我们 iOS 客户端的开发中,有一个长期困扰的问题:部分链接打开后,URL 里的参数被序列化了两次。
比如一个原始链接是这样的:
/path?fff[]=jjj ll
结果在 iOS 里打开后,变成了:
/path?fff%255B%255D=jjj%2520ll
注意看:
%5B 又变成了 %255B%20 又变成了 %2520也就是说,参数被二次序列化了。这个问题追了很久,直到最近才找到真正的原因。
在 iOS 标准库 中,[] 被认为是 需要编码的特殊字符。
所以 fff[] 会被序列化成 fff%5B%5D。
[] 不编码,因为很多 Web 框架(例如 PHP)习惯用 ids[] 这种形式传数组。
所以 <a> 标签或 document.createElement("a") 得到的结果里,[] 会原样保留。这就造成了一个差异:
fff[]=jjj ll → fff[]=jjj%20ll(空格被转义,[] 保留)fff[]=jjj ll → fff%5B%5D=jjj%20ll(空格和 [] 都被转义)当一个 URL 在不同环境下被“来回处理”时:
[] 没有被编码[] 必须编码 → %5B%5D%5B%5D 再做一次序列化 → %255B%255D这样,参数就被双重编码了。
在浏览器里:
var a = document.createElement("a");
a.href = "/path?fff[]=jjj ll";
console.log(a.search);
// 输出: ?fff[]=jjj%20ll
在 iOS(Swift)里:
let url = URL(string: "/path?fff[]=jjj ll", relativeTo: baseURL)!
print(url.query ?? "")
// 输出: fff%5B%5D=jjj%20ll
可以清楚看到差异。
在前端解析函数里,强制把 [] 也转义,保证跟 iOS 保持一致:
query: a.search
.replace(/ /g, "%20")
.replace(/\[/g, "%5B")
.replace(/\]/g, "%5D")
这样就不会出现“浏览器保留 [],iOS 又去二次编码”的情况。
使用标准化的 URL + URLSearchParams,而不是自己手写 split:
const u = new URL("/path?fff[]=jjj ll", location.origin);
console.log(u.search); // "?fff%5B%5D=jjj+ll"
console.log(u.searchParams.get("fff[]")); // "jjj ll"
这能确保在所有环境下,参数都被一致地编码。
这个问题折腾了我们很久,直到深入比对 iOS 与浏览器的标准才找到原因:
[] 不强制序列化[] 强制序列化于是跨环境传递 URL 时,很容易出现“二次序列化”的问题。
✅ 最佳实践:
[]URLSearchParams)这样,就能避免再掉进这个双重编码的坑。
非著名程序员,全栈开发工程师,长期专注系统开发与架构设计。
功能待开通!
在 IntelliJ IDEA 中,提示 “the file size exceeds the configured limit. Code insight features are not available” 表示当前文件的大小超出了 IDEA 的默认限制,因此无法启用代码自动提示、语法高亮等功能。默认文件大小限制为 2.5 MB。 解决方法 方
ProxySQL 是一个高性能、高可用性的 MySQL 代理,旨在为 MySQL 数据库提供负载均衡、读写分离、故障转移、查询缓存等高级功能。它通过在客户端和 MySQL 服务器之间充当中间层,实现对数据库连接和查询的智能管理,从而提升整体系统的性能和可靠性。
Base64 是一种常用的编码方式,用于将二进制数据转换为ASCII字符,以便在文本环境中安全地传输和存储。由于许多传输媒介(如电子邮件、HTTP协议)对二进制数据有特定的限制或处理方式,Base64提供了一种可靠的方法来确保数据在这些环境中的完整性和可读性。
迁移 Git 仓库是一个常见需求,尤其是在更换代码托管平台(如从 GitHub 迁移到 GitLab,或从本地仓库迁移到远程仓库)时。以下是几种常见的 Git 仓库迁移方法,具体使用哪种方法取决于你需要保留的内容(如历史记录、分支、
一、什么是 settings.xml settings.xml 是 Maven 的配置文件,用于定义用户级别或全局的构建配置。它包含了对 Maven 构建过程影响较大的设置,如: 本地仓库的位置 远程仓库的镜像 代理服务器配置 认证信息(如私有仓库的用户名和