如何将深层JSON的sites.site映射为Site模型?Ktor序列化报错求助
解决Ktor序列化嵌套JSON的问题
问题根源
你直接尝试将整个API响应体反序列化为List<Site>,但API返回的是多层嵌套结构:根对象包含sites字段,sites又包含count和site数组。序列化器找不到顶层数组,所以抛出"Expected start of the array '['"错误。另外你的Site数据类最后一行多了个逗号,会导致编译失败,需要先修正这个语法问题。
方案一:创建匹配响应结构的顶层数据类(推荐新手)
定义完整的响应结构类,先反序列化整个响应,再提取需要的site数组,逻辑清晰易维护。
步骤1:修正Site数据类
@Serializable data class Site ( @SerialName("id") val id: Int, @SerialName("name") val name: String, @SerialName("accountId") val accountId: Int // 去掉末尾多余的逗号 )
步骤2:定义响应结构类
@Serializable data class SiteListResponse( @SerialName("sites") val sites: SitesWrapper ) @Serializable data class SitesWrapper( @SerialName("count") val count: Int, @SerialName("site") val site: List<Site> )
步骤3:修改getSitesList方法
suspend fun getSitesList(): List<Site> { val response = get("sites/list").body<SiteListResponse>() return response.sites.site }
方案二:自定义序列化器直接提取嵌套数组(无需额外类)
如果不想写多余的响应结构类,可以用Kotlinx Serialization的自定义序列化器,直接定位到sites.site路径。
步骤1:创建自定义序列化器
class NestedListSerializer<T>(private val elementSerializer: KSerializer<T>) : KSerializer<List<T>> { override val descriptor: SerialDescriptor = elementSerializer.descriptor override fun serialize(encoder: Encoder, value: List<T>) { // 仅处理反序列化,序列化逻辑可留空 TODO("Not needed for deserialization") } override fun deserialize(decoder: Decoder): List<T> { val jsonDecoder = decoder as JsonDecoder val jsonElement = jsonDecoder.decodeJsonElement() // 定位到sites -> site数组 val siteArray = jsonElement.jsonObject["sites"]?.jsonObject?.get("site") ?: throw JsonDecodingException( decoder = decoder, message = "Could not find sites.site array" ) return jsonDecoder.json.decodeFromJsonElement(ListSerializer(elementSerializer), siteArray) } }
步骤2:修改getSitesList方法
suspend fun getSitesList(): List<Site> { val serializer = NestedListSerializer(Site.serializer()) return get("sites/list").body(serializer) }
方案三:手动解析JSON字符串(快速调试版)
直接获取响应文本后手动解析提取数组,逻辑直观,适合临时调试:
suspend fun getSitesList(): List<Site> { val jsonString = get("sites/list").bodyAsText() val jsonElement = Json.parseToJsonElement(jsonString) // 实际项目中建议替换!!为安全空处理,比如?:抛出自定义异常 val siteArray = jsonElement.jsonObject["sites"]!!.jsonObject["site"]!! return Json.decodeFromJsonElement<List<Site>>(siteArray) }
内容的提问来源于stack exchange,提问作者Ambidex
相关产品推荐
相关产品推荐

