Retrofit2 POST请求返回500错误,Postman正常,换参数名可正常请求
问题:Retrofit2 POST请求使用"userId"参数返回500错误,Postman正常
我试过StackOverflow上的多种方案都没解决,现在求助:用Retrofit2发起POST登录请求时返回500错误,但用Postman发送完全相同的请求却能正常响应。诡异的是,只要把请求JsonObject的属性名改成随机字符串,Retrofit2和Postman就都能正常拿到响应。已经咨询过服务器团队,对方表示服务器无问题,以下是相关代码,麻烦帮忙排查是否存在代码层面的问题。
接口定义
interface LoginService { @POST("api/v1/login") // POST fun requestLogin( // Input @Body loginData: JsonObject ): Call<LoginResponse> // Output }
LoginActivity代码
class LoginActivity : AppCompatActivity() { private lateinit var viewBinding : ActivityLoginBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewBinding = ActivityLoginBinding.inflate(layoutInflater) setContentView(viewBinding.root) // client val clientBuilder = OkHttpClient.Builder() val loggingInterceptor = HttpLoggingInterceptor() loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY clientBuilder.addInterceptor(loggingInterceptor) clientBuilder.retryOnConnectionFailure(true) // retrofit val retrofit = Retrofit.Builder() .baseUrl("secret") .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .client(clientBuilder.build()) // client .build() val userid = viewBinding.idt.text.toString() val password = viewBinding.pwdt.text.toString() val login = JsonObject() login.addProperty("userId", userid) login.addProperty("password", password) val loginService = retrofit.create(LoginService::class.java) viewBinding.signinbtn.setOnClickListener { loginService.requestLogin(login).enqueue(object: Callback<LoginResponse>{ override fun onResponse(call: Call<LoginResponse>, response: Response<LoginResponse>) { if (response.isSuccessful){ val responseData = response.body() if (responseData != null) { Log.d("Retrofit","ResponseCode: ${responseData.code} Message: ${responseData.message}") if (responseData.code == 1000) { val intent = Intent(this@LoginActivity, CalendarActivity::class.java) startActivity(intent) } if (responseData.code != 1000) { cuDialog(viewBinding.root, responseData.message) } if (responseData.code == 1000 && viewBinding.auto.isChecked) { } } } else { Log.w("Retrofit", "Response Not Successful ${response.code()}") } } override fun onFailure(call: Call<LoginResponse>, t: Throwable) { Log.e("Retrofit","Error!",t) val dialog = AlertDialog.Builder(this@LoginActivity) dialog.setTitle("오류") dialog.setMessage("서버와 통신에 실패했습니다.") dialog.show() } }) } }
响应数据类
data class LoginResponse( val isSuccess: Boolean, val code: Int, val message: String, val result: ArrayList<Info>)
关键异常现象
- 使用
"userId"和"password"作为参数名时,Retrofit2请求返回500错误,但Postman发送相同参数名的请求正常 - 将参数名改为随机字符串后,Retrofit2和Postman均能正常响应,示例代码:
val login = JsonObject() login.addProperty("sdfsfssdfd", userid) login.addProperty("sfsfdsfsd", password)
排查方向及解决方案
强制Gson保持字段原命名
Gson默认可能会将驼峰命名(如userId)自动转换为下划线命名(user_id),但Postman是直接发送原字段名。可以显式配置Gson保持字段名不变:val gson = GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY) .create() // 在Retrofit初始化时使用该Gson实例 val retrofit = Retrofit.Builder() ... .addConverterFactory(GsonConverterFactory.create(gson)) ...对比Retrofit与Postman的请求体
借助HttpLoggingInterceptor打印出Retrofit实际发送的请求体,和Postman的请求体逐字符对比:- 检查是否存在多余空格、转义字符差异
- 确认请求头的
Content-Type是否一致(均为application/json)
测试固定参数值
替换userid和password为固定测试值(如"testUser"、"123456"),排除参数值含特殊字符导致的服务器校验异常。确认服务器字段大小写敏感性
有些服务器框架对JSON字段名大小写敏感,通过日志确认Retrofit实际发送的字段名是否为userId(而非小写userid)。
内容的提问来源于stack exchange,提问作者juicy
相关产品推荐
相关产品推荐

