如何在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
}
解析地图(因为您拥有的“动态数据”只是一张地图)是Moshi开箱即用的功能。
从一开始就将Moshi依赖项添加到您的项目(moshi
和moshi-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)})