如何在Android kotlin,Moshi和Retrofit中使用动态键解析嵌套的JSON?

问题描述 投票:0回答:1

如何在Android kotlin,Moshi和Retrofit中使用动态键解析嵌套JSON?

格式示例:

{
    "Meta Data": {
        "1. Information": "Intraday (15min) open, high, low, close prices and volume",
        "2. Symbol": "AAME",
        "3. Last Refreshed": "2019-11-18 16:00:00",
        "4. Interval": "15min",
        "5. Output Size": "Compact",
        "6. Time Zone": "US/Eastern"
     },
    "Time Series (15min)": {//Dynamic - > Time Series (5min) / Time Series (30min)
        "2019-11-18 16:00:00": {//Dynamic
            "1. open": "1.6700",
            "2. high": "1.6700",
            "3. low": "1.5700",
            "4. close": "1.5700",
            "5. volume": "1521"
        },
        "2019-11-18 15:45:00": {//Dynamic
            "1. open": "1.6600",
            "2. high": "1.7400",
            "3. low": "1.6600",
            "4. close": "1.7400",
            "5. volume": "355"
        }
    }
}

我尝试使用自定义适配器,但是找不到用它解析双嵌套动态键的方法。现在,我使用手动解析:

fun convertJsonToItemDetails(jso: JSONObject) {
    val meta: JSONObject? = jso.optJSONObject("Meta Data")
    var metaData: ItemMetaData? = null
    meta?.apply {
        val information = optString("1. Information")
        val symbol = optString("2. Symbol")
        val lastRefreshed = optString("3. Last Refreshed")
        val interval = optString("4. Interval")
        val outputSize = optString("5. Output Size")
        val timeZone = optString("6. Time Zone")
        metaData =
            ItemMetaData(information, symbol, lastRefreshed, interval, outputSize, timeZone)
    }
    if (metaData == null) {
        //TODO return error object
        return
    }

    val timeSeriesJSON = jso.optJSONObject("Time Series (${metaData?.interval})")
    val timeSeires = HashMap<String, IntervalOutput>()
    if (timeSeriesJSON == null) {
        //TODO return error object
        return
    }
    for (key in timeSeriesJSON.keys()) {
        val intervalOutPutJSON = timeSeriesJSON.getJSONObject(key)
        val open = intervalOutPutJSON.getString("1. open")
        val high = intervalOutPutJSON.getString("2. high")
        val low = intervalOutPutJSON.getString("3. low")
        val close = intervalOutPutJSON.getString("4. close")
        val volume = intervalOutPutJSON.getString("5. volume")
        timeSeires[key] = IntervalOutput(open, high, low, close, volume)
    }
    val itemDetails = ItemDetails(metaData, timeSeires)
    _itemDetails.value = itemDetails
}
android kotlin retrofit2 kotlin-android-extensions moshi
1个回答
0
投票

解析地图(因为您拥有的“动态数据”只是一张地图)是Moshi开箱即用的功能。

从一开始就将Moshi依赖项添加到您的项目(moshimoshi-kotlin):

[build.gradle/dependencies]

implementation("com.squareup.moshi:moshi:1.9.2")
implementation("com.squareup.moshi:moshi-kotlin:1.9.2")

然后定义模型:

import com.squareup.moshi.Json

data class Root(
    @Json(name = "Meta Data")
    val metaData: MetaData,
    @Json(name = "Time Series (15min)")
    val timeSeries15: Map<String, TimeSeries>
)

data class MetaData(
    @Json(name = "1. Information")
    val information: String,
    @Json(name = "2. Symbol")
    val symbol: String
)

data class TimeSeries(
    @Json(name = "1. open")
    val open: String,
    @Json(name = "2. high")
    val high: String
)

然后...我们完成了! :D

让我们检查一下它是如何工作的:

val EXAMPLE = """ json here """
val parser: Moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

fun main() {
    val adapter = parser.adapter(Root::class.java);
    println(adapter.fromJson(EXAMPLE))
}

输出:

Root(metaData=MetaData(information=Intraday (15min) open, high, low, close prices and volume, symbol=AAME), timeSeries15={2019-11-18 16:00:00=TimeSeries(open=1.6700, high=1.6700), 2019-11-18 15:45:00=TimeSeries(open=1.6600, high=1.7400)})
© www.soinside.com 2019 - 2024. All rights reserved.