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

Retrofit中@QueryMap含空格参数的原样传递问题

问题:Retrofit QueryMap参数空格被自动编码,无法原样发送

接口定义

@GET("restful/api/search")
suspend fun librariesSearchBook(
    @Header("Authorization") access_token: String,
    @QueryMap(encoded = true) fData: Map<String, String>,
    @Query("term") term:String,
    @Query("page") page:Int,
):Response<SearchBooksResponse>

调用代码

fun facetLibrariesSpinnerItem(facetId:String?,item:String?,term: String){
    viewModelScope.launch (Dispatchers.IO ){
        val user = dataManager.getUser()
        val mapValue = mutableMapOf<String,String>()
        mapValue.put("f[0]", "$facetId:$item")

        try{
            val response = librarySearch.librariesSearchBook(user.access_token,mapValue,term,searchPageIndex)
            if(response.isSuccessful){
                    print(response)
            }

        }catch (exception: Exception){
            print(exception.message)
        }
    }
}

问题描述:传入的QueryMap参数包含带空格的字符串(如"Name: Hashir Hamza"),会被自动转换为"Name:%20Hashir%20Hamza",需要将参数原样发送给API。


解决方案

方法1:改用@Query单独指定参数并关闭编码

将f[0]参数从QueryMap中移出,单独使用@Query注解并设置encoded = true,这样Retrofit会直接使用你传入的原始字符串,不会自动编码:

修改后的接口定义:

@GET("restful/api/search")
suspend fun librariesSearchBook(
    @Header("Authorization") access_token: String,
    @Query("f[0]", encoded = true) facetValue: String?,
    @Query("term") term: String,
    @Query("page") page: Int,
): Response<SearchBooksResponse>

调用代码调整:

fun facetLibrariesSpinnerItem(facetId: String?, item: String?, term: String) {
    viewModelScope.launch(Dispatchers.IO) {
        val user = dataManager.getUser()
        val facetValue = if (facetId != null && item != null) "$facetId:$item" else null

        try {
            val response = librarySearch.librariesSearchBook(
                user.access_token,
                facetValue,
                term,
                searchPageIndex
            )
            if (response.isSuccessful) {
                print(response)
            }
        } catch (exception: Exception) {
            print(exception.message)
        }
    }
}

方法2:自定义OkHttpClient禁用URL编码(谨慎使用)

如果需要保留QueryMap的用法,可以配置OkHttpClient,让它不对Query参数进行编码。注意:这会影响所有请求的参数编码,可能导致其他参数不符合URL规范,仅在确认API接受原始空格的情况下使用:

val okHttpClient = OkHttpClient.Builder()
    .addInterceptor { chain ->
        val originalRequest = chain.request()
        val originalUrl = originalRequest.url

        // 手动构建URL,保留原始Query参数
        val newUrl = originalUrl.newBuilder()
            .query(originalUrl.query()) // 直接使用原始Query字符串,不编码
            .build()

        val newRequest = originalRequest.newBuilder()
            .url(newUrl)
            .build()

        chain.proceed(newRequest)
    }
    .build()

然后将这个OkHttpClient传入Retrofit构建器:

val retrofit = Retrofit.Builder()
    .baseUrl(BASE_URL)
    .client(okHttpClient)
    .addConverterFactory(GsonConverterFactory.create())
    .build()

注意事项

URL中直接包含空格不符合HTTP规范,大部分服务器会自动将空格解析为%20或+。如果你的API确实要求必须发送原始空格,才建议使用上述方法;否则优先确认API是否接受%20或+作为空格的替代方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:55:21