使用Retrofit2发送POST请求如何正确获取响应内嵌套的JSONObject
问题根因
你使用的GsonConverterFactory默认无法将服务端返回的JSON结构自动序列化到org.json.JSONObject类型的字段上,所以你拿到的data永远是空实例。
解决方法
方法1(最推荐):为Data字段定义对应数据类
这是Retrofit+Gson组合的标准用法,避免手动解析JSON的冗余代码和出错概率。
假设你接口返回的Data结构是{"userId":123,"nickname":"测试用户","token":"xxx"},先定义对应的数据类:
data class LoginData( @SerializedName("userId") val userId: Int, @SerializedName("nickname") val nickname: String, @SerializedName("token") val token: String )
然后修改你的JsonObjBase类,把data的类型换成你定义的这个类即可:
data class JsonObjBase ( @SerializedName("ResultCode") val resultCode : Int, @SerializedName("ResultValue") val resultValue : String, @SerializedName("ResultMessage") val resultMessage : String, @SerializedName("Data") val data : LoginData // 替换成你定义的Data对应数据类 )
之后直接在response.body()?.data里就能拿到所有字段值。
方法2:如果你确实需要拿到JSONObject对象
如果业务场景需要动态解析Data,不想写固定数据类,可以用下面两种实现:
方案A:用Gson内置的JsonObject类型接收
修改JsonObjBase的data字段类型为com.google.gson.JsonObject:
data class JsonObjBase ( @SerializedName("ResultCode") val resultCode : Int, @SerializedName("ResultValue") val resultValue : String, @SerializedName("ResultMessage") val resultMessage : String, @SerializedName("Data") val data : JsonObject )
拿到data后如果需要转成org.json.JSONObject,直接调用:
val jsonObj = JSONObject(data.toString())
方案B:直接拿原始响应自行解析
修改请求接口的返回类型为Call<ResponseBody>,拿到响应后自己转成JSONObject:
@POST("/api/Login") fun startLogin(@Body jsonObj: Operator) : Call<ResponseBody>
请求成功后的解析代码:
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>?) { response?.body()?.let { body -> val rootJson = JSONObject(body.string()) val dataJson = rootJson.getJSONObject("Data") // 自行解析dataJson里的字段 } }
额外注意
你现有代码存在命名不一致问题:你定义的接口名为APICall,但伴生对象里创建的是ApiInterface类型,需要统一命名否则会编译报错。
内容的提问来源于stack exchange,提问作者MovingRoot Lee
相关产品推荐
相关产品推荐

