kotlin 如何访问嵌套JSON,其中包含对每个API get结果唯一的行名称

ssgvzors  于 2023-02-13  发布在  Kotlin
关注(0)|答案(1)|浏览(168)

我的问题是,我试图从CoinMarketCap API获取单一加密货币信息。我使用JSON插件中的KKotlin数据类文件创建与我获得的API结果对应的数据类。CMC API请求返回以下内容:问题是,“data”后面的“1”对于每种加密货币都是唯一的。我使用插件创建了数据类,它创建的数据类对应于下面的JSON数据。它创建了一个名为X1的数据类,用于“1”行。当我试图获取比特币信息时,没有问题。但当我搜索以太坊时,例如,我得到了0和null,因为“data”后面的行这次不是“1”,而是“2”。最初创建的(“1”)不起作用,因为它试图获取存在1的行。但没有。如何忽略“数据”和“1”行并只获取其余的json数据?
创建的与“1”部件相关的数据类:

data class Data(
    @SerializedName("1")
    val x1: X1
)

data class X1(
    @SerializedName("circulating_supply")
    val circulatingSupply: Int,
    @SerializedName("cmc_rank")
    val cmcRank: Int,
    @SerializedName("date_added")
    val dateAdded: String,
    @SerializedName("id")
    val id: Int,
    @SerializedName("is_active")
    val isActive: Int,
    @SerializedName("is_fiat")
    val isFiat: Int,
    @SerializedName("last_updated")
    val lastUpdated: String,
    @SerializedName("max_supply")
    val maxSupply: Int,
    @SerializedName("name")
    val name: String,
    @SerializedName("num_market_pairs")
    val numMarketPairs: Int,
    @SerializedName("platform")
    val platform: Any,
    @SerializedName("quote")
    val quote: Quote,
    @SerializedName("self_reported_circulating_supply")
    val selfReportedCirculatingSupply: Any,
    @SerializedName("self_reported_market_cap")
    val selfReportedMarketCap: Any,
    @SerializedName("slug")
    val slug: String,
    @SerializedName("symbol")
    val symbol: String,
    @SerializedName("tags")
    val tags: List<String>,
    @SerializedName("total_supply")
    val totalSupply: Int
)

我用来创建数据类的JSON数据

{
"data": {
"1": {
"id": 1,
"name": "Bitcoin",
"symbol": "BTC",
"slug": "bitcoin",
"is_active": 1,
"is_fiat": 0,
"circulating_supply": 17199862,
"total_supply": 17199862,
"max_supply": 21000000,
"date_added": "2013-04-28T00:00:00.000Z",
"num_market_pairs": 331,
"cmc_rank": 1,
"last_updated": "2018-08-09T21:56:28.000Z",
"tags": [
"mineable"
],
"platform": null,
"self_reported_circulating_supply": null,
"self_reported_market_cap": null,
"quote": {
"USD": {
"price": 6602.60701122,
"volume_24h": 4314444687.5194,
"volume_change_24h": -0.152774,
"percent_change_1h": 0.988615,
"percent_change_24h": 4.37185,
"percent_change_7d": -12.1352,
"percent_change_30d": -12.1352,
"market_cap": 852164659250.2758,
"market_cap_dominance": 51,
"fully_diluted_market_cap": 952835089431.14,
"last_updated": "2018-08-09T21:56:28.000Z"
}
}
}
},
"status": {
"timestamp": "2023-02-02T16:19:58.335Z",
"error_code": 0,
"error_message": "",
"elapsed": 10,
"credit_count": 1
}
}

我试过忽略“1”行,但没有成功。我试过将其保留为“”,但也没有成功。我试过忽略“data”和“1”行,只为包含所需信息的其余行创建数据类。但没有成功。我得到了空值和0。我想学习如何为json数据调整SerializedName部分,因为在每个请求中都有唯一的行。如果这不可能,有没有办法只获取json数据中需要的部分?就像我上面说的,我试着获取“1”之后的数据:{尝试在此处获取数据}但不起作用。正在寻求有关此问题的帮助。

k97glaaz

k97glaaz1#

您可以通过以下方式实现:

class Repository @Inject constructor(
    private val service: MyRetrofitService
) {
    suspend fun getX1(): X1? {
        val call = service.getData()
        val response = call.execute()
        if (response.isSuccessful && response.body() != null) {
            // Search for Integer key in json which represents coin number and ignores string keys
            val json = response.body()!!
                .getAsJsonObject("data")
                .entrySet()
                .find {
                    it.key.toIntOrNull() != null
                }?.value ?: return null

            return Gson().fromJson(json, X1::class.java)
        }
        return null
    }
}

我的改造服务:

import com.google.gson.JsonObject    

interface MyService {
    @GET(YOUR_LINK)
    fun getData(): Call<JsonObject>
}

**解释:**Retrofit不能自动得到你想要的json部分,你必须自己去做。这是一个仓库函数的例子,你可以在那里得到你的X1类。我也不建议使用插件生成的数据类而不改变它。类型为Any的字段不能被正确解析,插件不知道哪些字段可以为空
**注意:**此代码不检查成功的请求。它只显示了通过将json转换为类来从json获取数据的方法

相关问题