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
相关产品推荐
相关产品推荐

