在 Kotlin 中使用 Moshi 和 Retrofit 解析具有增量对象名称的 JSON
Posted
技术标签:
【中文标题】在 Kotlin 中使用 Moshi 和 Retrofit 解析具有增量对象名称的 JSON【英文标题】:Parsing JSON with Increment Object Name using Moshi and Retrofit in Kotlin 【发布时间】:2021-08-24 22:08:06 【问题描述】:我通过类似这样的 API 获取 JSON。
如您所见,第一个对象名称是一个增量值。如何使用 moshi 处理数据类或接口中的变量对象名称? 对于“普通”JSON 文件,此代码有效。有没有办法让数据类对象名可变或者如何改变接口创建常量名?
数据类:
data class PhilipsHueLightsApi(
val lightId: List<HueLight>
)
data class HueLight(
val state: HueLightState,
val swupdate: HueLightSwupdate,
val type: String,
val name: String,
val modelid: String,
val manufacturername: String,
val productname: String,
val capabilities: HueLightCapabilities,
val config: HueLightConfig,
val uniqueid: String,
val swversion: String
)
data class HueLightState (
val on: Boolean,
val bri: Int,
val hue: Int,
val sat: Int,
val effect: String,
val xy: HueLightColorCode,
val ct: Int,
val alert: String,
val colormode: String,
val mode: String,
val reachable: Boolean
)...
API 服务:
interface OpenPhilipsHueConnection
/**
* A public interface that exposes the [getPhilipsHueLightsApi] method
*/
interface OneCallApiConnection
/**
* The @GET annotation indicates that endpoint will be requested with the GET HTTP method
*/
@GET("/$API_GET/$USER_ID/$API_SELECTION")
suspend fun getPhilipsHueLightsApi(): Response<PhilipsHueLightsApi>
// Singleton
object OpenPhilipsHueLightsApi
/**
* Build the Moshi object with Kotlin adapter factory that Retrofit will be using.
*/
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
/**
* The Retrofit object with the Moshi converter.
*/
private val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(BASE_URL)
.build()
val oneCallApi: OneCallApiConnection by lazy retrofit.create(OneCallApiConnection::class.java)
错误信息:
I/LightRepository: Failure: Required value 'lightId' missing at $
【问题讨论】:
不要在问题中使用代码截图,复制粘贴代码本身。 【参考方案1】:问题在于您对PhilipsHueLightsApi
的定义是具有lightId
类型List<HueLight>
的一个属性的对象的定义,并且与JSON 不匹配。
你得到的 JSON 也是一个对象,但它有多个属性,名称恰好是数字,这里没有涉及列表(或 JSON 数组)。
使用Map<String, HueLight>
而不是PhilipsHueLightsApi
类可以更好地表示这种格式。
您可能应该尝试像这样定义您的 API:
suspend fun getPhilipsHueLightsApi(): Response<Map<String, HueLight>>
【讨论】:
感谢您的快速响应。遗憾的是它不起作用:I/LightRepository: Failure: Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $.1.state.xy
@Ohlsen 问题在你的模型中更深层次。您应该尝试理解错误消息,它确实包含您需要的所有信息。查看错误中的路径,您已将属性 xy
定义为 Kotlin 中的对象,但它是 JSON 中的列表。您也应该在 Kotlin 声明中解决这个问题。您已经在那里隐藏了 JSON 数组的内容,所以我无法提供详细信息,但它应该非常简单
你是对的。它现在正在工作。非常感谢你的支持!!这对我帮助很大。以上是关于在 Kotlin 中使用 Moshi 和 Retrofit 解析具有增量对象名称的 JSON的主要内容,如果未能解决你的问题,请参考以下文章
如何在 moshi (kotlin) 中解析 LinkedHashMap
(Kotlin 中的 Moshi)@Json 与 @field:Json