Retrofit2 响应在 response.body 中成功,预期的对象列表为空
Retrofit2 response is succesfull in the response.body the expected List of objects is null
首先,我想说我是Android和Kotlin的新手,所以请耐心等待。话虽如此,我发现了一些与空改造响应相关的帖子,并且该响应可能是由错误数据引起的class,通常是与真实变量名称不同的变量名称JSON(通常,可以使用@SerializedName 批注解决此问题)。
我正在对我的服务器使用其他 enpoints,并且 Android 应用程序总是正确地获得响应(例如,只有一个 id 字段的 JSON 的简单响应)。所有端点都已使用 Postman 进行验证,我的一个朋友在他的 iOS 应用程序中使用相同的 API,并且对他来说效果很好。
改装是如何实例化的:
requestMaker.kt
interface ApiService {
@Headers("Content-Type: application/json")
@POST("getUserToken/")
suspend fun getUserToken(@Body userData: getUserTokenRequestData): Response<getUserTokenResponse>
@Headers("Content-Type: application/json")
@POST("registerNewUserWithTables/")
suspend fun signupNewUser(@Body userData: singupUserTokenRequestData): Response<singupUserTokenResponse>
@Headers("Content-Type: application/json")
@POST("getProductsByUserId/")
suspend fun getUserProductsById(@Body userData: getUserProductsByIdRequestData): Response<getUserProductsByIdResponse>
}
class RequestsMaker {
// Receive the context of the activity to pr
lateinit var data: String
object ApiClient {
private const val BASE_URL: String = "http://myserver.com/"
private val gson : Gson by lazy {
GsonBuilder().setLenient().create()
}
private val httpClient : OkHttpClient by lazy {
OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.build()
}
private val retrofit : Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
}
val apiService : ApiService by lazy{
retrofit.create(ApiService::class.java)
}
}
fun getRequestService():ApiService{
return ApiClient.apiService
}
}
数据 classes 已定义(我手动制作,但由于失败,我还使用了“来自 JSON 的 kotlin 数据 class 文件” Android Studio插件:
data class getUserProductsByIdRequestData(val id: Int)
data class getUserProductsByIdResponse(val products: productDataClass)
data class productDataClass(
val locations: List<Location>
)
data class Location(
val id: Int,
val storageAreas: List<StorageArea>
)
data class StorageArea(
val id: Int,
val products: List<Product>
)
data class Product(
val expirationDate: String,
val id: Int,
val name: String,
val purchaseDate: String
)
来自服务器的预期 JSON 响应是这样的(通过使用 Postman 获得):
POST请求
http://myserver.com/getProductsByUserId/
{
"id": 1
}
回应
{
"locations": [
{
"id": 2,
"storageAreas": [
{
"id": 2,
"products": [
{
"id": 4,
"name": "Ipad Goloso",
"purchaseDate": "2021-06-01",
"expirationDate": "2021-05-25"
}
]
}
]
}
]
}
我使用协程来调用,我是这样使用的:
private fun executeCall() {
var retrofit = RequestsMaker().getRequestService()
var request = getUserProductsByIdRequestData(id = 2)
GlobalScope.launch(Dispatchers.Main) {
try {
var response = retrofit.getUserProductsById(request)
if (response.isSuccessful && response.body() != null) {
val content = response.body()
if (content != null) {
Log.v("It worked message RESULT: ", content.toString())
}
}
else {
Log.w("Something went wrong with the request","lol")
//Toast.makeText(context, "Something went wrong with the request", Toast.LENGTH_LONG).show()
}
} catch (e: Exception) {
// This is the point to indicate the server is not responding
Log.e("ExceptionError message", e.message.toString())
Log.e("ExceptionError cause", e.cause.toString())
Log.e("ExceptionError localizedMessage", e.localizedMessage.toString())
Toast.makeText(applicationContext, "ERROR in the connection to the server", Toast.LENGTH_LONG).show()
}
}
}
但结果是检索到的产品始终为空...
任何想法都将非常受欢迎,因为几天后我没有找到任何关于如何解决这个问题的有用信息。
此致。
您的改装功能 returns getUserProductsByIdResponse。 class 期望在其构造函数中有一个 val products。它没有得到 - 响应的顶层是一个名为“location”的数组。因此产品字段(响应中唯一的字段)将被设置为空,其余数据将被丢弃。
换句话说,您的响应数据结构与实际返回的数据不匹配。你的结果有一个额外的层。可能是因为你写它是为了 returns 多个产品的单独请求,而这个 returns 一个产品。
首先,我想说我是Android和Kotlin的新手,所以请耐心等待。话虽如此,我发现了一些与空改造响应相关的帖子,并且该响应可能是由错误数据引起的class,通常是与真实变量名称不同的变量名称JSON(通常,可以使用@SerializedName 批注解决此问题)。
我正在对我的服务器使用其他 enpoints,并且 Android 应用程序总是正确地获得响应(例如,只有一个 id 字段的 JSON 的简单响应)。所有端点都已使用 Postman 进行验证,我的一个朋友在他的 iOS 应用程序中使用相同的 API,并且对他来说效果很好。
改装是如何实例化的:
requestMaker.kt
interface ApiService {
@Headers("Content-Type: application/json")
@POST("getUserToken/")
suspend fun getUserToken(@Body userData: getUserTokenRequestData): Response<getUserTokenResponse>
@Headers("Content-Type: application/json")
@POST("registerNewUserWithTables/")
suspend fun signupNewUser(@Body userData: singupUserTokenRequestData): Response<singupUserTokenResponse>
@Headers("Content-Type: application/json")
@POST("getProductsByUserId/")
suspend fun getUserProductsById(@Body userData: getUserProductsByIdRequestData): Response<getUserProductsByIdResponse>
}
class RequestsMaker {
// Receive the context of the activity to pr
lateinit var data: String
object ApiClient {
private const val BASE_URL: String = "http://myserver.com/"
private val gson : Gson by lazy {
GsonBuilder().setLenient().create()
}
private val httpClient : OkHttpClient by lazy {
OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.build()
}
private val retrofit : Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
}
val apiService : ApiService by lazy{
retrofit.create(ApiService::class.java)
}
}
fun getRequestService():ApiService{
return ApiClient.apiService
}
}
数据 classes 已定义(我手动制作,但由于失败,我还使用了“来自 JSON 的 kotlin 数据 class 文件” Android Studio插件:
data class getUserProductsByIdRequestData(val id: Int)
data class getUserProductsByIdResponse(val products: productDataClass)
data class productDataClass(
val locations: List<Location>
)
data class Location(
val id: Int,
val storageAreas: List<StorageArea>
)
data class StorageArea(
val id: Int,
val products: List<Product>
)
data class Product(
val expirationDate: String,
val id: Int,
val name: String,
val purchaseDate: String
)
来自服务器的预期 JSON 响应是这样的(通过使用 Postman 获得):
POST请求
http://myserver.com/getProductsByUserId/
{
"id": 1
}
回应
{
"locations": [
{
"id": 2,
"storageAreas": [
{
"id": 2,
"products": [
{
"id": 4,
"name": "Ipad Goloso",
"purchaseDate": "2021-06-01",
"expirationDate": "2021-05-25"
}
]
}
]
}
]
}
我使用协程来调用,我是这样使用的:
private fun executeCall() {
var retrofit = RequestsMaker().getRequestService()
var request = getUserProductsByIdRequestData(id = 2)
GlobalScope.launch(Dispatchers.Main) {
try {
var response = retrofit.getUserProductsById(request)
if (response.isSuccessful && response.body() != null) {
val content = response.body()
if (content != null) {
Log.v("It worked message RESULT: ", content.toString())
}
}
else {
Log.w("Something went wrong with the request","lol")
//Toast.makeText(context, "Something went wrong with the request", Toast.LENGTH_LONG).show()
}
} catch (e: Exception) {
// This is the point to indicate the server is not responding
Log.e("ExceptionError message", e.message.toString())
Log.e("ExceptionError cause", e.cause.toString())
Log.e("ExceptionError localizedMessage", e.localizedMessage.toString())
Toast.makeText(applicationContext, "ERROR in the connection to the server", Toast.LENGTH_LONG).show()
}
}
}
但结果是检索到的产品始终为空...
任何想法都将非常受欢迎,因为几天后我没有找到任何关于如何解决这个问题的有用信息。
此致。
您的改装功能 returns getUserProductsByIdResponse。 class 期望在其构造函数中有一个 val products。它没有得到 - 响应的顶层是一个名为“location”的数组。因此产品字段(响应中唯一的字段)将被设置为空,其余数据将被丢弃。
换句话说,您的响应数据结构与实际返回的数据不匹配。你的结果有一个额外的层。可能是因为你写它是为了 returns 多个产品的单独请求,而这个 returns 一个产品。