You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 19:27:01