Dart/Flutter如何禁用URI对%字符自动转义为%25的机制
问题根因
Dart的Uri类提供的Uri.http/Uri.https构造方法中,第三个参数queryParameters会强制对所有键、值做标准化转义,默认编码为UTF-8,且会把传入值里的%当成普通字符转义为%25,所以你之前的三种写法都达不到预期:
- 直接传
ß会被默认用UTF-8编码为%C3%9F - 传预编码的
%DF会被二次转义为%25DF - 先用latin1转好
%DF再传入queryParameters,还是会触发二次转义
可行解决方案
不要使用queryParameters参数传参,手动构造符合latin1编码的查询字符串后直接拼接到路径参数中即可,Uri不会对路径中已经符合URI规范的转义字符做二次处理:
单参数场景直接拼接
// 先单独用latin1编码目标字符,得到%DF final encodedValue = Uri.encodeQueryComponent('ß', encoding: latin1); // 直接拼到路径里,不要走queryParameters参数 final uri = Uri.http('some.domain', 'json.php?key=$encodedValue');
此时uri.toString()的结果就是你需要的http://some.domain/json.php?key=%DF。
多参数场景封装工具方法
如果有多个查询参数,可以封装通用的编码方法,避免手动拼接出错:
import 'dart:convert'; String encodeLatin1QueryParams(Map<String, String> params) { return params.entries.map((entry) { final encodedKey = Uri.encodeQueryComponent(entry.key, encoding: latin1); final encodedValue = Uri.encodeQueryComponent(entry.value, encoding: latin1); return '$encodedKey=$encodedValue'; }).join('&'); } // 使用示例 final queryStr = encodeLatin1QueryParams({'key': 'ß', 'otherParam': 'test'}); final uri = Uri.http('some.domain', 'json.php?$queryStr');
注意事项
Dart的Uri类设计初衷是生成符合标准规范的URI,没有提供关闭自动转义的开关,也不建议强制修改其转义逻辑,绕过queryParameters参数手动构造查询串是成本最低、兼容性最好的方案。
内容的提问来源于stack exchange,提问作者Bridystone
相关产品推荐
相关产品推荐

