如何在更深层次的JSON数据结构上使用@Serializer



我是Kotlin的一名PHP开发人员。我有一个数据模型,如下所示:

@Serializable
data class Site (
@SerialName("id")
val id: Int,
@SerialName("name")
val name: String,
@SerialName("accountId")
val accountId: Int,
}

我有如下JSON输出,它来自外部API,我无法控制:

{
"sites": {
"count": 1,
"site": [
{
"id": 12345,
"name": "Foobar",
"accountId": 123456 
}
]
}
}

当试图通过ktor HTTPClient从API获取这一点时,我希望指示序列化程序使用sites.site作为Site数据模型的根。目前,我得到错误:Uncaught Kotlin exception: io.ktor.serialization.JsonConvertException: Illegal inputCaused by: kotlinx.serialization.json.internal.JsonDecodingException: Expected start of the array '[', but had 'EOF' instead at path: $

我正在使用以下内容来获取端点:

package com.example.myapplication.myapp
import com.example.myapplication.myapp.models.Site
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json
class Api {
private val client = HttpClient {
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
})
}
}
private val apiKey = "REDACTED"
private val installationId = "REDACTED"
private val apiHost = "REDACTED"
suspend fun getSitesList(): List<Site> {
return get("sites/list").body()
}
suspend fun get(endpoint: String): HttpResponse {
val response = client.get(buildEndpointUrl(endpoint))
return response
}
private fun buildEndpointUrl(endpoint: String): HttpRequestBuilder {
val builder = HttpRequestBuilder()
val parametersBuilder = ParametersBuilder()
parametersBuilder.append("api_key", apiKey)
builder.url {
protocol = URLProtocol.HTTPS
host = apiHost
encodedPath = endpoint
encodedParameters = parametersBuilder
}
builder.header("Accept", "application/json")
return builder
}
}

您必须对整个响应对象建模,而不能只为其某些部分提供模型。

@Serializable
data class SitesResponse(
val sites: SitesContainer,
)
@Serializable
data class SitesContainer(
val count: Int,
val site: List<Site>,
)
@Serializable
data class Site(    
val accountId: Int,
val id: Int,
val name: String,
)

您可以尝试使您的数据模型像这样,

data class Site(
@SerializedName("sites")
var sites: Sites) {
data class Sites(
@SerializedName("count")
var count: Int,
@SerializedName("site")
var site: List<Site>
) {
data class Site(
@SerializedName("accountId")
var accountId: Int,
@SerializedName("id")
var id: Int,
@SerializedName("name")
var name: String
)
}}

最新更新