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

Flutter中Retrofit+Dio如何将空格编码为%20而非+?

解决Dio+Retrofit查询参数空格编码为%20而非+的问题

问题场景

使用Dio+Retrofit发起HTTP请求时,查询参数"KURZEMES PROSPEKTS"被自动编码为"KURZEMES+PROSPEKTS",但业务需求需要将空格编码为%20。现有代码如下:

@GET('v2/address')
Future<AddressHouses> getAddressesHouses(
  @Query('street_name', encoded: true) String? streetName,
);

解决方案

方法1:手动编码参数,关闭Retrofit自动编码

将@Query的encoded参数设为false,然后手动使用Uri.encodeComponent处理参数(该方法会将空格转为%20):

修改接口定义:

@GET('v2/address')
Future<AddressHouses> getAddressesHouses(
  @Query('street_name', encoded: false) String? streetName,
);

调用接口时手动编码:

String targetStreet = "KURZEMES PROSPEKTS";
// 手动编码空格为%20
String encodedStreet = Uri.encodeComponent(targetStreet);
await yourApiInstance.getAddressesHouses(encodedStreet);

方法2:全局配置Dio的查询参数编码器

如果需要所有查询参数都统一使用%20编码空格,可以直接配置Dio的queryEncoder,替换默认的编码逻辑:

// 初始化Dio时设置自定义查询编码器
final dio = Dio()
  ..options.queryEncoder = (String param) => Uri.encodeComponent(param);

// 用配置好的Dio创建Retrofit实例
final api = RestApi(dio);

此时接口定义可以恢复默认(无需设置encoded: true):

@GET('v2/address')
Future<AddressHouses> getAddressesHouses(
  @Query('street_name') String? streetName,
);

调用时直接传入原始字符串即可,Dio会自动将空格编码为%20。

方法3:手动拼接URL(应急方案)

如果上述方式都不适用,可直接构造完整的请求URL(不推荐,不利于维护):

修改接口定义:

@GET()
Future<AddressHouses> getAddressesHouses(
  @Url() String fullUrl,
);

调用时拼接编码后的URL:

String targetStreet = "KURZEMES PROSPEKTS";
String encodedStreet = Uri.encodeComponent(targetStreet);
String fullUrl = "v2/address?street_name=$encodedStreet";
await yourApiInstance.getAddressesHouses(fullUrl);

原理说明

默认情况下,Dio/Retrofit使用Uri.encodeQueryComponent编码查询参数,该方法遵循application/x-www-form-urlencoded规范,将空格转为+;而Uri.encodeComponent遵循RFC 3986标准,将空格转为%20,这正是我们需要的编码方式。

内容的提问来源于stack exchange,提问作者GDTyka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 08:24:59