Android Kotlin Retrofit发起多参数POST请求返回500错误排查
问题成因
请求失败的核心原因是序列化配置和传参类型不匹配,具体触发点如下:
- 你为Retrofit配置的序列化转换器是
GsonConverterFactory,但接口的@Body参数使用了org.json.JSONObject类型。Gson无法正确识别该类的结构,不会按照你传入的JSON字符串内容生成请求体,最终发送给后端的是结构畸形的JSON内容,后端解析请求体失败直接返回500错误。 - 接口声明的返回值是
Call<String>,但仅配置了Gson转换器,Gson会默认尝试将响应内容按JSON结构解析,如果接口返回的是普通纯文本字符串,会触发解析异常,最终读取到的响应体为null。 - Postman可以正常请求是因为Postman直接发送你手动输入的原始请求体内容,不存在代码层面的序列化转换逻辑,和Android端的请求执行逻辑有本质区别。
修复方案
按以下步骤调整代码即可恢复正常请求:
- 第一步:替换请求体传参类型,不要使用
org.json.JSONObject,改用Gson可以正常序列化的Map结构或者自定义数据类,以Map为例,构建和你需求完全匹配的请求体:
// 构建对应结构的请求体 val requestBody = mapOf( "some_field" to mapOf( "55" to "29" ) )
同时修改Retrofit接口定义的@Body参数类型:
@POST("customers/{customers}/venues/{venues}/abcfiles/sasfordownload") fun makeRequestForfileUrl( @HeaderMap token: Map<String, String>, @Path("customers") customers: Int, @Path("venues") venues: Int, @Query("licenseid") licenceId: String, @Query("ispreproduction") ispreproduction: Boolean, @Body body: Map<String, Any> // 替换原有的JSONObject类型 ): Call<String>
- 第二步:添加字符串响应转换器,支持直接解析String类型的返回值。注意
ScalarsConverterFactory必须放在GsonConverterFactory之前声明,否则不会生效。
先引入和你当前Retrofit版本匹配的scalars依赖,之后修改Retrofit实例构建代码:
fun requestApi(mContext: Context): ApiInterface { return Retrofit.Builder() .baseUrl(apiUrl) // 优先添加Scalars转换器处理纯文本/字符串响应 .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .client( OkHttpClient.Builder() .addInterceptor(NetworkConnectionInterceptor(mContext)) // 建议将日志拦截器级别设置为BODY,可直接查看实际发出的请求/响应内容 .addInterceptor(httpLoggingInterceptor) .build() ) .build() .create(ApiInterface::class.java) }
- 第三步:发起请求时,传入之前构建的
requestBody替换原有的JSONObject实例即可:
val headerMap = HashMap<String, String>().apply { put("Authorization", "Bearer $fetchedToken") put("Content-Type", "application/json") } val requestCall = ServiceGenerator.requestApi(mContext).makeRequestForfileUrl( headerMap, customerId, venueId, licenceId, true, requestBody )
排查提示:将HttpLoggingInterceptor的日志级别设置为
BODY后,可以直接在Logcat中看到Android端实际发出的请求头、请求地址、请求体、响应内容,和Postman的请求参数做逐行对比,可快速定位所有参数差异问题。
内容的提问来源于stack exchange,提问作者Vinit ...
相关产品推荐
相关产品推荐

