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 一个产品。