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

Multipart表单请求中布尔参数无法被服务端正常识别问题

Retrofit Multipart请求中布尔参数无法被服务端识别的解决方案

问题场景

使用Retrofit开发时,发送包含布尔参数enabled、字符串参数name及文件photo的@Multipart POST请求,服务端仅对布尔参数返回错误:"The enabled field must be true or false."。单独发送JSON格式的布尔参数时服务端可正常识别,但JSON请求无法携带文件。

问题分析

从请求详情可以看到,Retrofit默认将布尔参数enabled序列化为纯文本字符串"true"或"false",而服务端的参数验证规则可能仅接受布尔类型的原始值(部分后端框架如Laravel在处理表单请求时,会将字符串"true"判定为非布尔类型,不符合验证规则)。而JSON请求中布尔值会被序列化为原生布尔格式,因此能被服务端正确识别。

解决方案

方案1:将布尔参数转为整数类型传递

将布尔值转为1(代表true)或0(代表false)的整数,适配服务端对数值型布尔的解析逻辑:

修改接口定义:

@Multipart
@POST("auth/...")
suspend fun sendExampleRequest(
    @Part("enabled") enabled: Int,
    @Part("name") name: String,
    @Part photo: MultipartBody.Part
)

调用时转换参数:

override suspend fun sendExampleRequest(
    enabled: Boolean,
    name: String,
    photo : Uri
) {
    try {
        withContext(ioDispatcher) {
            authApi.sendExampleRequest(
                enabled = if(enabled) 1 else 0,
                name = name,
                photo = document.toMultipartBodyPart(context, "photo")
            )
        }
    } catch (e: Throwable) {
        // 异常处理
    }
}

方案2:手动将布尔参数序列化为JSON格式的RequestBody

通过RequestBody将布尔值序列化为JSON原生格式,确保服务端识别为布尔类型:

修改接口定义:

@Multipart
@POST("auth/...")
suspend fun sendExampleRequest(
    @Part("enabled") enabled: RequestBody,
    @Part("name") name: String,
    @Part photo: MultipartBody.Part
)

调用时构建JSON格式的RequestBody:

override suspend fun sendExampleRequest(
    enabled: Boolean,
    name: String,
    photo : Uri
) {
    try {
        withContext(ioDispatcher) {
            val enabledBody = RequestBody.create(
                MediaType.parse("application/json"),
                gson.toJson(enabled) // 使用已配置的Gson实例序列化布尔值
            )
            authApi.sendExampleRequest(
                enabled = enabledBody,
                name = name,
                photo = document.toMultipartBodyPart(context, "photo")
            )
        }
    } catch (e: Throwable) {
        // 异常处理
    }
}

此方案下,请求中的enabled字段会以application/json类型传递原生布尔值,与单独发送JSON请求时的格式一致,服务端可正确解析。

方案3:全局自定义Converter处理布尔参数(可选)

如果多个接口存在相同问题,可自定义Retrofit的Converter,自动将@Part中的布尔参数转换为服务端期望的格式。示例如下:

  1. 创建自定义Converter工厂:
class BooleanPartConverterFactory : Converter.Factory() {
    override fun requestBodyConverter(
        type: Type,
        parameterAnnotations: Array<Annotation>,
        methodAnnotations: Array<Annotation>,
        retrofit: Retrofit
    ): Converter<*, RequestBody>? {
        return if (type == Boolean::class.javaPrimitiveType || type == Boolean::class.java) {
            Converter<Boolean, RequestBody> { value ->
                RequestBody.create(MediaType.parse("application/json"), gson.toJson(value))
            }
        } else {
            super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit)
        }
    }
}
  1. 在Retrofit配置中添加该Converter(注意顺序,需放在GsonConverterFactory之前):
@Provides
@Singleton
fun provideRetrofit(
    gson: Gson,
    client: OkHttpClient,
    queryConverterFactory: Converter.Factory
): Retrofit = Retrofit.Builder()
    .baseUrl(BuildConfig.BASE_URL)
    .client(client)
    .addConverterFactory(queryConverterFactory)
    .addConverterFactory(BooleanPartConverterFactory()) // 添加自定义Converter
    .addConverterFactory(ScalarsConverterFactory.create())
    .addConverterFactory(GsonConverterFactory.create(gson))
    .build()

配置完成后,无需修改接口和调用代码,Retrofit会自动处理布尔类型的@Part参数。

验证

采用上述方案后,查看请求详情:

  • 方案1中enabled字段内容为1或0
  • 方案2/3中enabled字段的Content-Type为application/json,内容为true或false

此时服务端可正确识别布尔参数,不再返回验证错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 11:24:55